blob: 5fd21583a6008d32b22a8cff5ef9cde9f16ac7d4 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070035#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundbladec7114722020-08-13 05:11:40 -070036#include "ieee754.h" // Does not use math.h
37
38#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade323f8a92020-09-06 19:43:09 -070039#include <math.h> // For isnan(), llround(), llroudf(), round(), roundf(),
40 // pow(), exp2()
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -070041#include <fenv.h> // feclearexcept(), fetestexcept()
Laurence Lundblade1ddc1f22020-12-06 05:29:05 -080042#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070043
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070044
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053045/*
46 This casts away the const-ness of a pointer, usually so it can be
47 freed or realloced.
48 */
49#define UNCONST_POINTER(ptr) ((void *)(ptr))
50
Laurence Lundbladea9489f82020-09-12 13:50:56 -070051#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070052
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070053
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070054static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070055QCBORItem_IsMapOrArray(const QCBORItem *pMe)
56{
57 const uint8_t uDataType = pMe->uDataType;
58 return uDataType == QCBOR_TYPE_MAP ||
59 uDataType == QCBOR_TYPE_ARRAY ||
60 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
61}
62
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070063static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070064QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
65{
66 if(!QCBORItem_IsMapOrArray(pMe)){
67 return false;
68 }
69
70 if(pMe->val.uCount != 0) {
71 return false;
72 }
73 return true;
74}
75
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070076static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070077QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
78{
Laurence Lundbladec7fc5882020-12-03 04:31:37 -080079#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -070080 if(!QCBORItem_IsMapOrArray(pMe)){
81 return false;
82 }
83
84 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
85 return false;
86 }
87 return true;
Laurence Lundbladec7fc5882020-12-03 04:31:37 -080088#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
89 (void)pMe;
90 return false;
91#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -070092}
93
94
Laurence Lundbladeee851742020-01-08 08:37:05 -080095/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070096 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080097 ===========================================================================*/
98
Laurence Lundblade9c905e82020-04-25 11:31:38 -070099/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700100 See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
Laurence Lundblade93d89472020-10-03 22:30:50 -0700101 the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700102 */
103
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700104
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700105static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700106DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700107{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700108 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700109 /*
110 Limit in DecodeNesting_Descend against more than
111 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
112 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700113 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700114}
115
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700116
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700117static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700118DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700119{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700120 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700121 /*
122 Limit in DecodeNesting_Descend against more than
123 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
124 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700125 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700126}
127
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700128
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700129static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700130DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700131{
132 return pNesting->pCurrentBounded->u.ma.uStartOffset;
133}
134
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700135
Laurence Lundblade085d7952020-07-24 10:26:30 -0700136static inline bool
137DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
138{
139 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
140 return true;
141 } else {
142 return false;
143 }
144}
145
146
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700147static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700148DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700149{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700150 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700151 return true;
152 } else {
153 return false;
154 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700155}
156
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700157
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700158static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700159DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700160{
161 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700162 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700163 return false;
164 }
Laurence Lundbladec7fc5882020-12-03 04:31:37 -0800165
166#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700167 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700168 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700169 return false;
170 }
Laurence Lundblade1ddc1f22020-12-06 05:29:05 -0800171#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
172
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700173 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700174 return true;
175}
176
Laurence Lundbladec7fc5882020-12-03 04:31:37 -0800177#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700178static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700179DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700180{
181 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700182 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700183 return true;
184 }
185 return false;
186}
Laurence Lundbladec7fc5882020-12-03 04:31:37 -0800187#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700188
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700189
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700190static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700191{
192 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
193 return true;
194 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700195 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700196 return true;
197 }
198 return false;
199}
200
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700201
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700202static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700203{
204 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700205 /*
206 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
207 larger than DecodeNesting_EnterBoundedMode which keeps it less than
208 uin32_t so the cast is safe.
209 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700210 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700211
212 if(bIsEmpty) {
213 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
214 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700215}
216
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700217
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700218static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700219{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700220 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700221}
222
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700223
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700224static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700225DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700226{
227 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700228 // No bounded map or array set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700229 return false;
230 }
231 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700232 // Not a map or array; end of those is by byte count
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700233 return false;
234 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700235 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
236 // In a traveral at a level deeper than the bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700237 return false;
238 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700239 // Works for both definite and indefinite length maps/arrays
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800240 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
241 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700242 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700243 return false;
244 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700245 // All checks passed, got to the end of an array or map
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700246 return true;
247}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700248
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700249
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700250static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700251DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700252{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700253 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700254 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
255 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700256 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700257 return false;
258 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700259}
260
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700261
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700262static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700263DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700264{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700265 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
266 return true;
267 } else {
268 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700269 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700270}
271
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700272
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700273static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700274DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700275{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700276 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700277 return false;
278 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700279
280 if(pNesting->pCurrentBounded->uLevelType != uType) {
281 return false;
282 }
283
284 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700285}
286
Laurence Lundblade02625d42020-06-25 14:41:41 -0700287
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700288static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700289DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700290{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700291 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700292 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700293}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700294
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700295
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700296static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700297DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
298{
299 // Only call on a defnite length array / map
300 pNesting->pCurrent->u.ma.uCountCursor++;
301}
302
303
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700304static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700305DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
306{
307 pNesting->pCurrent--;
308}
309
Laurence Lundblade02625d42020-06-25 14:41:41 -0700310
311static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700312DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700313{
314 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700315 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700316 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700317 }
318
319 // The actual descend
320 pNesting->pCurrent++;
321
322 pNesting->pCurrent->uLevelType = uType;
323
324 return QCBOR_SUCCESS;
325}
326
327
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700328static inline QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700329DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700330{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700331 /*
332 Should only be called on map/array.
333
334 Have descended into this before this is called. The job here is
335 just to mark it in bounded mode.
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700336
337 Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
338 uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700339 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700340 if(uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700341 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700342 }
343
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700344 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700345
346 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700347
348 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700349}
350
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700351
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700352static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700353DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700354 uint8_t uQCBORType,
355 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700356{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700357 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700358
359 if(uCount == 0) {
360 // Nothing to do for empty definite lenth arrays. They are just are
361 // effectively the same as an item that is not a map or array
362 goto Done;
363 // Empty indefinite length maps and arrays are handled elsewhere
364 }
365
366 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700367 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
368 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700369 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700370 goto Done;
371 }
372
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700373 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700374 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700375 goto Done;
376 }
377
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700378 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700379 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
380 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700381
382 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700383
384Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700385 return uError;;
386}
387
388
389static inline void
390DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
391{
392 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
393}
394
395
396static inline void
397DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
398{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700399 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700400 pNesting->pCurrentBounded--;
401 if(DecodeNesting_IsCurrentBounded(pNesting)) {
402 break;
403 }
404 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700405}
406
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700407static inline void
408DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
409{
410 pNesting->pCurrent = pNesting->pCurrentBounded;
411}
412
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700413
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700414static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700415DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700416 uint32_t uEndOffset,
417 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700418{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700419 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700420
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700421 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700422 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700423 goto Done;
424 }
425
Laurence Lundblade02625d42020-06-25 14:41:41 -0700426 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700427 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
428 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700429
Laurence Lundblade02625d42020-06-25 14:41:41 -0700430 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700431 pNesting->pCurrentBounded = pNesting->pCurrent;
432
433Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700434 return uError;;
435}
436
Laurence Lundbladed0304932020-06-27 10:59:38 -0700437
438static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700439DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700440{
441 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700442}
443
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700444
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700445static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800446DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
447{
448 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
449}
450
451
452static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700453DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700454{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700455 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700456 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
457 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700458}
459
460
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700461static inline void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700462DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700463{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700464 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700465 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800466 DecodeNesting_ResetMapOrArrayCount(pNesting);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700467}
468
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700469
Laurence Lundblade02625d42020-06-25 14:41:41 -0700470static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700471DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700472{
473 *pNesting = *pSave;
474}
475
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700476
Laurence Lundblade02625d42020-06-25 14:41:41 -0700477static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700478DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700479{
480 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
481}
482
483
Laurence Lundblade02625d42020-06-25 14:41:41 -0700484static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700485DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700486{
487 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
488}
489
490
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800491#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800492/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800493 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
494
495 The following four functions are pretty wrappers for invocation of
496 the string allocator supplied by the caller.
497
Laurence Lundbladeee851742020-01-08 08:37:05 -0800498 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800499
Laurence Lundbladeee851742020-01-08 08:37:05 -0800500static inline void
501StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800502{
503 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
504}
505
Laurence Lundbladeee851742020-01-08 08:37:05 -0800506// StringAllocator_Reallocate called with pMem NULL is
507// equal to StringAllocator_Allocate()
508static inline UsefulBuf
509StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
510 void *pMem,
511 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800512{
513 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
514}
515
Laurence Lundbladeee851742020-01-08 08:37:05 -0800516static inline UsefulBuf
517StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800518{
519 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
520}
521
Laurence Lundbladeee851742020-01-08 08:37:05 -0800522static inline void
523StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800524{
525 if(pMe->pfAllocator) {
526 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
527 }
528}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800529#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800530
531
Laurence Lundbladeee851742020-01-08 08:37:05 -0800532/*===========================================================================
533 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700534
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800535 See qcbor/qcbor_decode.h for definition of the object
536 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800537 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700538/*
539 Public function, see header file
540 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800541void QCBORDecode_Init(QCBORDecodeContext *me,
542 UsefulBufC EncodedCBOR,
543 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700544{
545 memset(me, 0, sizeof(QCBORDecodeContext));
546 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800547 // Don't bother with error check on decode mode. If a bad value is
548 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700549 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700550 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700551 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700552 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700553 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700554}
555
556
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800557#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
558
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700559/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700560 Public function, see header file
561 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800562void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
563 QCBORStringAllocate pfAllocateFunction,
564 void *pAllocateContext,
565 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700566{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800567 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
568 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
569 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700570}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800571#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700572
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800573
574/*
575 Public function, see header file
576 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700577void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800578 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700579{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700580 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700581 (void)pMe;
582 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700583}
584
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700585
586/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800587 This decodes the fundamental part of a CBOR data item, the type and
588 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800589
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700590 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800591
Laurence Lundbladeee851742020-01-08 08:37:05 -0800592 This does the network->host byte order conversion. The conversion
593 here also results in the conversion for floats in addition to that
594 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800595
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700596 This returns:
597 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800598
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800599 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800600 tags and floats and length for strings and arrays
601
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800602 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800603 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800604
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800605 The int type is preferred to uint8_t for some variables as this
606 avoids integer promotions, can reduce code size and makes
607 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700608
609 @retval QCBOR_ERR_UNSUPPORTED
610
611 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700612 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700613static inline QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800614 int *pnMajorType,
615 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800616 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700617{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700618 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800619
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700620 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800621 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800622
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700623 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800624 const int nTmpMajorType = nInitialByte >> 5;
625 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800626
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800627 // Where the number or argument accumulates
628 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800629
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800630 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700631 // Need to get 1,2,4 or 8 additional argument bytes. Map
632 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800633 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800634
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800635 // Loop getting all the bytes in the argument
636 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800637 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800638 // This shift and add gives the endian conversion
639 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
640 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800641 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800642 // The reserved and thus-far unused additional info values
643 nReturn = QCBOR_ERR_UNSUPPORTED;
644 goto Done;
645 } else {
646 // Less than 24, additional info is argument or 31, an indefinite length
647 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800648 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700649 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800650
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651 if(UsefulInputBuf_GetError(pUInBuf)) {
652 nReturn = QCBOR_ERR_HIT_END;
653 goto Done;
654 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800655
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700656 // All successful if we got here.
657 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800658 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800659 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800660 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800661
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700662Done:
663 return nReturn;
664}
665
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800666
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700667/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800668 CBOR doesn't explicitly specify two's compliment for integers but all
669 CPUs use it these days and the test vectors in the RFC are so. All
670 integers in the CBOR structure are positive and the major type
671 indicates positive or negative. CBOR can express positive integers
672 up to 2^x - 1 where x is the number of bits and negative integers
673 down to 2^x. Note that negative numbers can be one more away from
674 zero than positive. Stdint, as far as I can tell, uses two's
675 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800676
Laurence Lundblade9b334962020-08-27 10:55:53 -0700677 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800678 used carefully here, and in particular why it isn't used in the interface.
679 Also see
680 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
681
682 Int is used for values that need less than 16-bits and would be subject
683 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700684
685 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700686 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700687static inline QCBORError
Laurence Lundbladeee851742020-01-08 08:37:05 -0800688DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700689{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700690 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800691
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700692 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
693 if (uNumber <= INT64_MAX) {
694 pDecodedItem->val.int64 = (int64_t)uNumber;
695 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800696
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700697 } else {
698 pDecodedItem->val.uint64 = uNumber;
699 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800700
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701 }
702 } else {
703 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800704 // CBOR's representation of negative numbers lines up with the
705 // two-compliment representation. A negative integer has one
706 // more in range than a positive integer. INT64_MIN is
707 // equal to (-INT64_MAX) - 1.
708 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700709 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800710
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700711 } else {
712 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000713 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700714 nReturn = QCBOR_ERR_INT_OVERFLOW;
715 }
716 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800717
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700718 return nReturn;
719}
720
721// Make sure #define value line up as DecodeSimple counts on this.
722#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
723#error QCBOR_TYPE_FALSE macro value wrong
724#endif
725
726#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
727#error QCBOR_TYPE_TRUE macro value wrong
728#endif
729
730#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
731#error QCBOR_TYPE_NULL macro value wrong
732#endif
733
734#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
735#error QCBOR_TYPE_UNDEF macro value wrong
736#endif
737
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700738#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
739#error QCBOR_TYPE_BREAK macro value wrong
740#endif
741
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
743#error QCBOR_TYPE_DOUBLE macro value wrong
744#endif
745
746#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
747#error QCBOR_TYPE_FLOAT macro value wrong
748#endif
749
750/*
751 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700752
753 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
754
755 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700756 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700757static inline QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800758DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700759{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700760 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800761
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700762 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800763 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundblade93d89472020-10-03 22:30:50 -0700764 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast
765 // is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800766 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800767
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800768 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800769 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
770 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800771
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700772 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700773#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700774 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700775 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700776 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700777 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
778 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade1ddc1f22020-12-06 05:29:05 -0800779#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700780 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade1ddc1f22020-12-06 05:29:05 -0800781#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700782 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700783 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700784 // Single precision is normally returned as a double
785 // since double is widely supported, there is no loss of
786 // precision, it makes it easy for the caller in
787 // most cases and it can be converted back to single
788 // with no loss of precision
789 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700790 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700791 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700792 {
793 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
794#ifndef QCBOR_DISABLE_FLOAT_HW_USE
795 // In the normal case, use HW to convert float to double.
796 pDecodedItem->val.dfnum = (double)f;
797 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade1ddc1f22020-12-06 05:29:05 -0800798#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700799 // Use of float HW is disabled, return as a float.
800 pDecodedItem->val.fnum = f;
801 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
802
803 // IEEE754_FloatToDouble() could be used here to return
804 // as a double, but it adds object code and most likely
805 // anyone disabling FLOAT HW use doesn't care about
806 // floats and wants to save object code.
Laurence Lundblade1ddc1f22020-12-06 05:29:05 -0800807#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700808 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700809 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700810
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700811 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700812 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700813 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700814 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800815
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700816 case CBOR_SIMPLEV_FALSE: // 20
817 case CBOR_SIMPLEV_TRUE: // 21
818 case CBOR_SIMPLEV_NULL: // 22
819 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700820 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700821 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800822
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700823 case CBOR_SIMPLEV_ONEBYTE: // 24
824 if(uNumber <= CBOR_SIMPLE_BREAK) {
825 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700826 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700827 goto Done;
828 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800829 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700830 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800831
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700832 default: // 0-19
833 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800834 /*
835 DecodeTypeAndNumber will make uNumber equal to
836 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
837 safe because the 2, 4 and 8 byte lengths of uNumber are in
838 the double/float cases above
839 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700840 pDecodedItem->val.uSimple = (uint8_t)uNumber;
841 break;
842 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800843
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700844Done:
845 return nReturn;
846}
847
848
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700849/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530850 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700851
852 @retval QCBOR_ERR_HIT_END
853
854 @retval QCBOR_ERR_STRING_ALLOCATE
855
856 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700857 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700858static inline QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800859 uint64_t uStrLen,
860 UsefulInputBuf *pUInBuf,
861 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700862{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700863 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800864
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800865 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
866 // This check makes the casts to size_t below safe.
867
868 // 4 bytes less than the largest sizeof() so this can be tested by
869 // putting a SIZE_MAX length in the CBOR test input (no one will
870 // care the limit on strings is 4 bytes shorter).
871 if(uStrLen > SIZE_MAX-4) {
872 nReturn = QCBOR_ERR_STRING_TOO_LONG;
873 goto Done;
874 }
875
876 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530877 if(UsefulBuf_IsNULLC(Bytes)) {
878 // Failed to get the bytes for this string item
879 nReturn = QCBOR_ERR_HIT_END;
880 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700881 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530882
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800883#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800884 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530885 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800886 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530887 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700888 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530889 goto Done;
890 }
891 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800892 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800893 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530894 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800895#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
896 (void)pAllocator;
897#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
898
899 // Normal case with no string allocator
900 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800901
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530902Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700903 return nReturn;
904}
905
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700906
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800907/* Map the CBOR major types for strings to the QCBOR types for strngs */
908static inline uint8_t MapStringMajorTypes(int nCBORMajorType)
909{
910 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
911 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
912 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800913
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800914 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
915 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
916 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700917
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800918 return (uint8_t)(nCBORMajorType + 4);
919}
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700920
921
Laurence Lundbladeee851742020-01-08 08:37:05 -0800922// Make sure the constants align as this is assumed by
923// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700924#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
925#error QCBOR_TYPE_ARRAY value not lined up with major type
926#endif
927#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
928#error QCBOR_TYPE_MAP value not lined up with major type
929#endif
930
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700931/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800932 This gets a single data item and decodes it including preceding
933 optional tagging. This does not deal with arrays and maps and nesting
934 except to decode the data item introducing them. Arrays and maps are
935 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800936
Laurence Lundbladeee851742020-01-08 08:37:05 -0800937 Errors detected here include: an array that is too long to decode,
938 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700939
940 @retval QCBOR_ERR_UNSUPPORTED
941
942 @retval QCBOR_ERR_HIT_END
943
944 @retval QCBOR_ERR_INT_OVERFLOW
945
946 @retval QCBOR_ERR_STRING_ALLOCATE
947
948 @retval QCBOR_ERR_STRING_TOO_LONG
949
950 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
951
952 @retval QCBOR_ERR_BAD_TYPE_7
953
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700954 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800955static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
956 QCBORItem *pDecodedItem,
957 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700958{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700959 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800960
Laurence Lundbladeee851742020-01-08 08:37:05 -0800961 /*
962 Get the major type and the number. Number could be length of more
963 bytes or the value depending on the major type nAdditionalInfo is
964 an encoding of the length of the uNumber and is needed to decode
965 floats and doubles
966 */
Rob Gilton47cc9562020-08-10 12:03:38 +0100967 int nMajorType = 0;
968 uint64_t uNumber = 0;
969 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800970
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700971 memset(pDecodedItem, 0, sizeof(QCBORItem));
972
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800973 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800974
Laurence Lundbladeee851742020-01-08 08:37:05 -0800975 // Error out here if we got into trouble on the type and number. The
976 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700977 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700978 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700979 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800980
Laurence Lundbladeee851742020-01-08 08:37:05 -0800981 // At this point the major type and the value are valid. We've got
982 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800983 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700984 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
985 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800986 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700987 nReturn = QCBOR_ERR_BAD_INT;
988 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800989 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700990 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700991 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800992
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700993 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
994 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800995 pDecodedItem->uDataType = MapStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800996 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800997 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700998 } else {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800999 nReturn = DecodeBytes(pAllocator, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001000 }
1001 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001002
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001003 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
1004 case CBOR_MAJOR_TYPE_MAP: // Major type 5
1005 // Record the number of items in the array or map
1006 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001007 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001008 goto Done;
1009 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001010 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladec7fc5882020-12-03 04:31:37 -08001011#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001012 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade1ddc1f22020-12-06 05:29:05 -08001013#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladec7fc5882020-12-03 04:31:37 -08001014 nReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1015 break;
Laurence Lundblade1ddc1f22020-12-06 05:29:05 -08001016#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001017 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001018 // type conversion OK because of check above
1019 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001020 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001021 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001022 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001023 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001024 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001025
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001026 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001027 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001028 nReturn = QCBOR_ERR_BAD_INT;
1029 } else {
1030 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001031 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001032 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001033 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001034
Laurence Lundbladeee851742020-01-08 08:37:05 -08001035 case CBOR_MAJOR_TYPE_SIMPLE:
1036 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001037 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001038 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001039
Laurence Lundbladeee851742020-01-08 08:37:05 -08001040 default:
1041 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001042 nReturn = QCBOR_ERR_UNSUPPORTED;
1043 break;
1044 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001045
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001046Done:
1047 return nReturn;
1048}
1049
1050
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001051/**
1052 * @brief Process indefinite length strings
1053 *
1054 * @param[in] pMe Decoder context
1055 * @param[in,out] pDecodedItem The decoded item that work is done on.
1056 *
1057 * @retval QCBOR_ERR_UNSUPPORTED
1058 * @retval QCBOR_ERR_HIT_END
1059 * @retval QCBOR_ERR_INT_OVERFLOW
1060 * @retval QCBOR_ERR_STRING_ALLOCATE
1061 * @retval QCBOR_ERR_STRING_TOO_LONG
1062 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1063 * @retval QCBOR_ERR_BAD_TYPE_7
1064 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1065 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1066 *
1067 * If @c pDecodedItem is not an indefinite length string, this does nothing.
1068 *
1069 * If it is, this loops getting the subsequent chunks that make up the
1070 * string. The string allocator is used to make a contiguous buffer for
1071 * the chunks. When this completes @c pDecodedItem contains the
1072 * put-together string.
1073 *
1074 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001075 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001076static inline QCBORError
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001077GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001078{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001079 /* Aproximate stack usage
1080 * 64-bit 32-bit
1081 * local vars 32 16
1082 * 2 UsefulBufs 32 16
1083 * QCBORItem 56 52
1084 * TOTAL 120 74
1085 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001086
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001087 /* The string allocator is used here for two purposes: 1)
1088 * coalescing the chunks of an indefinite length string, 2)
1089 * allocating storage for every string returned.
1090 *
1091 * The first use is below in this function. Indefinite length
1092 * strings cannot be processed at all without a string allocator.
1093 *
1094 * The second used is in DecodeBytes() which is called by
1095 * GetNext_Item() below. This second use unneccessary for most use
1096 * and only happens when requested in the call to
1097 * QCBORDecode_SetMemPool(). If the second use not requested then
1098 * NULL is passed for the string allocator to GetNext_Item().
1099 *
1100 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1101 * allocator altogether and thus both of these uses. It reduced the
1102 * decoder object code by about 400 bytes.
1103 */
1104 const QCORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001105
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001106#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1107 const QCORInternalAllocator *pAllocator = NULL;
1108
1109 if(pMe->StringAllocator.pfAllocator) {
1110 pAllocator = &(pMe->StringAllocator);
1111 if(pMe->bStringAllocateAll) {
1112 pAllocatorForGetNext = pAllocator;
1113 }
1114 }
1115#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1116
1117 QCBORError uReturn;
1118 uReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
1119 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001120 goto Done;
1121 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001122
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001123 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001124 const uint8_t uStringType = pDecodedItem->uDataType;
1125 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001126 goto Done;
1127 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001128
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001129 /* Is this a string with an indefinite length? */
1130 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1131 goto Done;
1132 }
1133
1134#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1135 /* Can't do indefinite length strings without a string allocator */
1136 if(pAllocator == NULL) {
1137 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1138 goto Done;
1139 }
1140
1141 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001142 UsefulBufC FullString = NULLUsefulBufC;
1143
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001144 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001145 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001146 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001147 /* Pass a NULL string allocator to GetNext_Item() because the
1148 * individual string chunks in an indefinite length should not
1149 * be allocated. They are always copied in the the contiguous
1150 * buffer allocated here.
1151 */
1152 uReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
1153 if(uReturn) {
1154 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001155 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001156
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001157 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001158 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001159 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001160 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301161 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001162 break;
1163 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001164
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001165 /* All chunks must be of the same type, the type of the item
1166 * that introduces the indefinite length string. This also
1167 * catches errors where the chunk is not a string at all and an
1168 * indefinite length string inside an indefinite length string.
1169 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001170 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001171 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1172 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001173 break;
1174 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001175
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001176 /* The first time throurgh FullString.ptr is NULL and this is
1177 * equivalent to StringAllocator_Allocate(). Subsequently it is
1178 * not NULL and a reallocation happens.
1179 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001180 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1181 UNCONST_POINTER(FullString.ptr),
1182 FullString.len + StringChunkItem.val.string.len);
1183
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001184 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001185 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001186 break;
1187 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001188
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001189 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001190 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001191 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001192
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001193 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1194 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001195 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001196 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001197#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1198 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1199#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001200
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001201Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001202 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001203}
1204
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001205
Laurence Lundblade9b334962020-08-27 10:55:53 -07001206static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001207 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001208 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001209 } else if(uTagVal == CBOR_TAG_INVALID16) {
1210 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001211 } else {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001212 // This won't be negative because of code below in GetNext_TaggedItem()
1213 const unsigned uIndex = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
1214 return me->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001215 }
1216}
1217
Laurence Lundblade9b334962020-08-27 10:55:53 -07001218
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001219/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001220 Gets all optional tag data items preceding a data item that is not an
1221 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001222
1223 @retval QCBOR_ERR_UNSUPPORTED
1224
1225 @retval QCBOR_ERR_HIT_END
1226
1227 @retval QCBOR_ERR_INT_OVERFLOW
1228
1229 @retval QCBOR_ERR_STRING_ALLOCATE
1230
1231 @retval QCBOR_ERR_STRING_TOO_LONG
1232
1233 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1234
1235 @retval QCBOR_ERR_BAD_TYPE_7
1236
1237 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1238
1239 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1240
1241 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001242 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001243static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001244GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001245{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001246 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1247 CBOR_TAG_INVALID16,
1248 CBOR_TAG_INVALID16,
1249 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001250
Laurence Lundblade9b334962020-08-27 10:55:53 -07001251 QCBORError uReturn = QCBOR_SUCCESS;
1252
Laurence Lundblade59289e52019-12-30 13:44:37 -08001253 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001254 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001255 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1256 if(uErr != QCBOR_SUCCESS) {
1257 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001258 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001259 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001260
Laurence Lundblade9b334962020-08-27 10:55:53 -07001261 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001262 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001263 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001264 break;
1265 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001266
Laurence Lundblade9b334962020-08-27 10:55:53 -07001267 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1268 // No room in the tag list
1269 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1270 // Continue on to get all tags on this item even though
1271 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001272 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001273 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001274 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001275 // Slide tags over one in the array to make room at index 0
1276 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1277 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001278 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001279
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001280 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001281 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001282 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001283 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001284 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001285 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001286 break;
1287 }
1288 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1289 break;
1290 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001291 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001292 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1293 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001294 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1295 // Continue on to get all tags on this item even though
1296 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001297 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001298 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001299 }
1300
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001301 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001302 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001303 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001304
1305 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001306 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001307 }
1308 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001309
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001310Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001311 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001312}
1313
1314
1315/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001316 This layer takes care of map entries. It combines the label and data
1317 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001318
1319 @retval QCBOR_ERR_UNSUPPORTED
1320
1321 @retval QCBOR_ERR_HIT_END
1322
1323 @retval QCBOR_ERR_INT_OVERFLOW
1324
1325 @retval QCBOR_ERR_STRING_ALLOCATE
1326
1327 @retval QCBOR_ERR_STRING_TOO_LONG
1328
1329 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1330
1331 @retval QCBOR_ERR_BAD_TYPE_7
1332
1333 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1334
1335 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1336
1337 @retval QCBOR_ERR_TOO_MANY_TAGS
1338
1339 @retval QCBOR_ERR_MAP_LABEL_TYPE
1340
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001341 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001342 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001343static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001344GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001345{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001346 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001347 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001348 if(nReturn)
1349 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001350
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001351 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001352 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001353 goto Done;
1354 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001355
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001356 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1357 // In a map and caller wants maps decoded, not treated as arrays
1358
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001359 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001360 // If in a map and the right decoding mode, get the label
1361
Laurence Lundbladeee851742020-01-08 08:37:05 -08001362 // Save label in pDecodedItem and get the next which will
1363 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001364 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001365 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001366 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001367 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001368 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001369
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301370 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001371
1372 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1373 // strings are always good labels
1374 pDecodedItem->label.string = LabelItem.val.string;
1375 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1376 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001377 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001378 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1379 goto Done;
1380 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1381 pDecodedItem->label.int64 = LabelItem.val.int64;
1382 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1383 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1384 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1385 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1386 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1387 pDecodedItem->label.string = LabelItem.val.string;
1388 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1389 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1390 } else {
1391 // label is not an int or a string. It is an arrray
1392 // or a float or such and this implementation doesn't handle that.
1393 // Also, tags on labels are ignored.
1394 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1395 goto Done;
1396 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001397 }
1398 } else {
1399 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001400 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001401 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001402 goto Done;
1403 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001404 // Decoding a map as an array
1405 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001406 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1407 // Cast is needed because of integer promotion
1408 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001409 }
1410 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001411
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001412Done:
1413 return nReturn;
1414}
1415
1416
Laurence Lundbladec7fc5882020-12-03 04:31:37 -08001417#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001418/*
1419 See if next item is a CBOR break. If it is, it is consumed,
1420 if not it is not consumed.
1421*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001422static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001423NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1424{
1425 *pbNextIsBreak = false;
1426 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001427 QCBORItem Peek;
1428 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1429 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1430 if(uReturn != QCBOR_SUCCESS) {
1431 return uReturn;
1432 }
1433 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001434 // It is not a break, rewind so it can be processed normally.
1435 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001436 } else {
1437 *pbNextIsBreak = true;
1438 }
1439 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001440
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001441 return QCBOR_SUCCESS;
1442}
Laurence Lundbladec7fc5882020-12-03 04:31:37 -08001443#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001444
1445
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001446/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001447 An item was just consumed, now figure out if it was the
1448 end of an array or map that can be closed out. That
1449 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001450*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001451static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001452{
1453 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001454
Laurence Lundblade642282a2020-06-23 12:00:33 -07001455 /* This loops ascending nesting levels as long as there is ascending to do */
1456 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1457
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001458 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001459 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001460 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1461 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001462 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001463 break;
1464 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07001465 /* All of a definite length array was consumed; fall through to
1466 ascend */
Laurence Lundbladec7fc5882020-12-03 04:31:37 -08001467#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade642282a2020-06-23 12:00:33 -07001468
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001469 } else {
Laurence Lundbladec7fc5882020-12-03 04:31:37 -08001470
Laurence Lundblade02625d42020-06-25 14:41:41 -07001471 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001472 bool bIsBreak = false;
1473 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1474 if(uReturn != QCBOR_SUCCESS) {
1475 goto Done;
1476 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001477
1478 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001479 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001480 break;
1481 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001482
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001483 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001484 /*
1485 Break occurred inside a bstr-wrapped CBOR or
1486 in the top level sequence. This is always an
1487 error because neither are an indefinte length
1488 map/array.
1489 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001490 uReturn = QCBOR_ERR_BAD_BREAK;
1491 goto Done;
1492 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001493 /* It was a break in an indefinite length map / array */
Laurence Lundbladec7fc5882020-12-03 04:31:37 -08001494
Laurence Lundblade1ddc1f22020-12-06 05:29:05 -08001495#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001496 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001497
Laurence Lundbladec7fc5882020-12-03 04:31:37 -08001498
Laurence Lundblade02625d42020-06-25 14:41:41 -07001499 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001500
Laurence Lundblade93d89472020-10-03 22:30:50 -07001501 /* But ascent in bounded mode is only by explicit call to
1502 QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001503 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001504 /* Set the count to zero for definite length arrays to indicate
1505 cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001506 if(bMarkEnd) {
1507 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001508 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001509
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001510 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001511 break;
1512 }
1513
1514 /* Finally, actually ascend one level. */
1515 DecodeNesting_Ascend(&(pMe->nesting));
1516 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001517
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001518 uReturn = QCBOR_SUCCESS;
1519
Laurence Lundbladec7fc5882020-12-03 04:31:37 -08001520#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001521Done:
Laurence Lundbladec7fc5882020-12-03 04:31:37 -08001522#endif /* #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1523
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001524 return uReturn;
1525}
1526
1527
1528/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001529 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001530 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1531 indefinte length maps and arrays by looking at the item count or
1532 finding CBOR breaks. It detects the ends of the top-level sequence
1533 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001534
1535 @retval QCBOR_ERR_UNSUPPORTED X
1536
1537 @retval QCBOR_ERR_HIT_END
1538
1539 @retval QCBOR_ERR_INT_OVERFLOW X
1540
1541 @retval QCBOR_ERR_STRING_ALLOCATE
1542
1543 @retval QCBOR_ERR_STRING_TOO_LONG
1544
1545 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1546
1547 @retval QCBOR_ERR_BAD_TYPE_7 X
1548
1549 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1550
1551 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1552
1553 @retval QCBOR_ERR_TOO_MANY_TAGS
1554
1555 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1556
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001557 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001558
1559 @retval QCBOR_ERR_NO_MORE_ITEMS
1560
1561 @retval QCBOR_ERR_BAD_BREAK
1562
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001563 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001564static QCBORError
1565QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001566{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001567 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001568 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001569
Laurence Lundblade642282a2020-06-23 12:00:33 -07001570 /*
1571 If out of bytes to consume, it is either the end of the top-level
1572 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001573
Laurence Lundblade642282a2020-06-23 12:00:33 -07001574 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1575 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1576 CBOR is exited, the length is set back to the top-level's length
1577 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001578 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001579 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001580 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001581 goto Done;
1582 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001583
Laurence Lundblade642282a2020-06-23 12:00:33 -07001584 /*
1585 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001586 array. The check for the end of an indefinite length array is
1587 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001588 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001589 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001590 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001591 goto Done;
1592 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001593
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001594 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001595 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001596 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1597 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001598 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001599 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301600
Laurence Lundblade642282a2020-06-23 12:00:33 -07001601 /*
1602 Breaks ending arrays/maps are always processed at the end of this
1603 function. They should never show up here.
1604 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301605 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001606 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301607 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301608 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001609
Laurence Lundblade642282a2020-06-23 12:00:33 -07001610 /*
1611 Record the nesting level for this data item before processing any
1612 of decrementing and descending.
1613 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001614 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001615
Laurence Lundblade642282a2020-06-23 12:00:33 -07001616
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001617 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001618 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001619 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001620 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001621
Laurence Lundblade93d89472020-10-03 22:30:50 -07001622 Empty indefinite length maps and arrays are descended into, but
1623 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001624
1625 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001626 encloses them so a decrement needs to be done for them too, but
1627 that is done only when all the items in them have been
1628 processed, not when they are opened with the exception of an
1629 empty map or array.
1630 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001631 QCBORError uDescendErr;
1632 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001633 pDecodedItem->uDataType,
1634 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001635 if(uDescendErr != QCBOR_SUCCESS) {
1636 /* This error is probably a traversal error and it
1637 overrides the non-traversal error. */
1638 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001639 goto Done;
1640 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001641 }
1642
Laurence Lundblade02625d42020-06-25 14:41:41 -07001643 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1644 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1645 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001646 /*
1647 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001648 - A non-aggregate like an integer or string
1649 - An empty definite length map or array
1650 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001651
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001652 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001653 definite length map/array and break detection for an indefinite
1654 length map/array. If the end of the map/array was reached, then
1655 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001656 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001657 QCBORError uAscendErr;
1658 uAscendErr = NestLevelAscender(me, true);
1659 if(uAscendErr != QCBOR_SUCCESS) {
1660 /* This error is probably a traversal error and it
1661 overrides the non-traversal error. */
1662 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001663 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001664 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301665 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001666
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001667 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001668 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001669 Tell the caller what level is next. This tells them what
1670 maps/arrays were closed out and makes it possible for them to
1671 reconstruct the tree with just the information returned in
1672 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001673 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001674 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001675 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001676 pDecodedItem->uNextNestLevel = 0;
1677 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001678 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001679 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001680
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001681Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001682 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001683}
1684
Laurence Lundblade9b334962020-08-27 10:55:53 -07001685static void ShiftTags(QCBORItem *pDecodedItem)
1686{
1687 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1688 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1689 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1690 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1691}
1692
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001693
Laurence Lundblade9b334962020-08-27 10:55:53 -07001694
Laurence Lundblade59289e52019-12-30 13:44:37 -08001695/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001696 The epoch formatted date. Turns lots of different forms of encoding
1697 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001698 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001699static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001700{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001701 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001702
1703 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1704
1705 switch (pDecodedItem->uDataType) {
1706
1707 case QCBOR_TYPE_INT64:
1708 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1709 break;
1710
1711 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001712 // This only happens for CBOR type 0 > INT64_MAX so it is
1713 // always an overflow.
1714 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1715 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001716 break;
1717
1718 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001719 case QCBOR_TYPE_FLOAT:
1720#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001721 {
1722 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001723 // conversion to an int64_t to be able to detect doubles that
1724 // are too large to fit into an int64_t. A double has 52
1725 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1726 // to a double actually causes a round up which is bad and
1727 // wrong for the comparison because it will allow conversion
1728 // of doubles that can't fit into a uint64_t. To remedy this
1729 // INT64_MAX - 0x7ff is used as the cutoff point because if
1730 // that value rounds up in conversion to double it will still
1731 // be less than INT64_MAX. 0x7ff is picked because it has 11
1732 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001733 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001734 // INT64_MAX seconds is on the order of 10 billion years, and
1735 // the earth is less than 5 billion years old, so for most
1736 // uses this conversion error won't occur even though doubles
1737 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001738 //
1739 // Without the 0x7ff there is a ~30 minute range of time
1740 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001741 // where this code would go wrong. Some compilers
1742 // will generate warnings or errors without the 0x7ff
1743 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001744 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1745 pDecodedItem->val.dfnum :
1746 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001747 if(isnan(d) ||
1748 d > (double)(INT64_MAX - 0x7ff) ||
1749 d < (double)(INT64_MIN + 0x7ff)) {
1750 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001751 goto Done;
1752 }
1753 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001754 pDecodedItem->val.epochDate.fSecondsFraction =
1755 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001756 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001757#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001758
Laurence Lundbladec7114722020-08-13 05:11:40 -07001759 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001760 goto Done;
1761
Laurence Lundblade9682a532020-06-06 18:33:04 -07001762#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001763 break;
1764
1765 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001766 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001767 goto Done;
1768 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001769
Laurence Lundblade59289e52019-12-30 13:44:37 -08001770 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1771
1772Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001773 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001774}
1775
1776
1777#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1778/*
1779 Decode decimal fractions and big floats.
1780
1781 When called pDecodedItem must be the array that is tagged as a big
1782 float or decimal fraction, the array that has the two members, the
1783 exponent and mantissa.
1784
1785 This will fetch and decode the exponent and mantissa and put the
1786 result back into pDecodedItem.
1787 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001788static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001789QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1790{
1791 QCBORError nReturn;
1792
1793 // --- Make sure it is an array; track nesting level of members ---
1794 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1795 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1796 goto Done;
1797 }
1798
1799 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001800 // definite length arrays, but not for indefnite. Instead remember
1801 // the nesting level the two integers must be at, which is one
1802 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001803 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1804
1805 // --- Is it a decimal fraction or a bigfloat? ---
1806 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1807 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1808
1809 // --- Get the exponent ---
1810 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001811 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001812 if(nReturn != QCBOR_SUCCESS) {
1813 goto Done;
1814 }
1815 if(exponentItem.uNestingLevel != nNestLevel) {
1816 // Array is empty or a map/array encountered when expecting an int
1817 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1818 goto Done;
1819 }
1820 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1821 // Data arriving as an unsigned int < INT64_MAX has been converted
1822 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1823 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1824 // will be too large for this to handle and thus an error that will
1825 // get handled in the next else.
1826 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1827 } else {
1828 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1829 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1830 goto Done;
1831 }
1832
1833 // --- Get the mantissa ---
1834 QCBORItem mantissaItem;
1835 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1836 if(nReturn != QCBOR_SUCCESS) {
1837 goto Done;
1838 }
1839 if(mantissaItem.uNestingLevel != nNestLevel) {
1840 // Mantissa missing or map/array encountered when expecting number
1841 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1842 goto Done;
1843 }
1844 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1845 // Data arriving as an unsigned int < INT64_MAX has been converted
1846 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1847 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1848 // will be too large for this to handle and thus an error that
1849 // will get handled in an else below.
1850 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001851 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1852 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001853 // Got a good big num mantissa
1854 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1855 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001856 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1857 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1858 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001859 } else {
1860 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1861 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1862 goto Done;
1863 }
1864
1865 // --- Check that array only has the two numbers ---
1866 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001867 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001868 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1869 goto Done;
1870 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001871 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001872
1873Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001874 return nReturn;
1875}
1876#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1877
1878
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001879static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001880{
1881 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1882 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001883 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001884 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1885 } else {
1886 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001887
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001888 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001889
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001890 return QCBOR_SUCCESS;
1891}
1892
1893
Laurence Lundblade99615302020-11-29 11:19:47 -08001894/*
1895 * Table of CBOR tags whose content is either a text string or a byte
1896 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
1897 * of uQCBORtype indicates the content should be a byte string rather
1898 * than a text string
1899 */
1900struct StringTagMapEntry {
1901 uint16_t uTagNumber;
1902 uint8_t uQCBORtype;
1903};
1904
1905#define IS_BYTE_STRING_BIT 0x80
1906#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
1907
1908static const struct StringTagMapEntry StringTagMap[] = {
1909 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
1910 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
1911 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
1912 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
1913 {CBOR_TAG_URI, QCBOR_TYPE_URI},
1914 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
1915 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
1916 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
1917 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
1918 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
1919 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
1920};
1921
1922
1923/*
1924 * Process the CBOR tags that whose content is a byte string or a text
1925 * string and for which the string is just passed on to the caller.
1926 *
1927 * This maps the CBOR tag to the QCBOR type and checks the content
1928 * type. Nothing more. It may not be the most important
1929 * functionality, but it part of implementing as much of RFC 7049 as
1930 * possible.
1931 *
1932 * This returns QCBOR_SUCCESS if the tag was procssed,
1933 * QCBOR_ERR_UNSUPPORTED if the tag was not processed and
1934 * QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
1935 */
1936static inline
1937QCBORError ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001938{
Laurence Lundblade99615302020-11-29 11:19:47 -08001939 /* This only works on tags that were not mapped; no need for other yet */
1940 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
1941 return QCBOR_ERR_UNSUPPORTED;
1942 }
1943
1944 unsigned uIndex;
1945 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
1946 if(StringTagMap[uIndex].uTagNumber == uTag) {
1947 break;
1948 }
1949 }
1950
1951 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
1952 if(uQCBORType == QCBOR_TYPE_NONE) {
1953 /* repurpose this error to mean, not handled here */
1954 return QCBOR_ERR_UNSUPPORTED;
1955 }
1956
1957 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
1958 if(uQCBORType & IS_BYTE_STRING_BIT) {
1959 uExpectedType = QCBOR_TYPE_BYTE_STRING;
1960 }
1961
1962 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001963 return QCBOR_ERR_BAD_OPT_TAG;
1964 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001965
Laurence Lundblade99615302020-11-29 11:19:47 -08001966 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001967 return QCBOR_SUCCESS;
1968}
1969
1970
Laurence Lundblade59289e52019-12-30 13:44:37 -08001971/*
Laurence Lundblade99615302020-11-29 11:19:47 -08001972 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
1973 * but the whole tag was not decoded. Here, the whole tags (tag number
1974 * and tag content) that are supported by QCBOR are decoded. This is a
1975 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001976 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001977static QCBORError
1978QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001979{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001980 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001981
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001982 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
1983 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001984 goto Done;
1985 }
1986
Laurence Lundblade99615302020-11-29 11:19:47 -08001987 /* When there are no tag numbers for the item, this exits first
1988 * thing and effectively does nothing.
1989 *
1990 * This loops over all the tag numbers accumulated for this item
1991 * trying to decode and interpret them. This stops at the end of
1992 * the list or at the first tag number that can't be interpreted by
1993 * this code. This is effectively a recursive processing of the
1994 * tags number list that handles nested tags.
1995 */
1996 while(1) {
1997 /* Don't bother to unmap tags via QCBORITem.uTags since this
1998 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
1999 */
2000 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002001
Laurence Lundblade99615302020-11-29 11:19:47 -08002002 if(uTagToProcess == CBOR_TAG_INVALID16) {
2003 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002004 break;
2005
Laurence Lundblade99615302020-11-29 11:19:47 -08002006 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002007 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002008
Laurence Lundblade93d89472020-10-03 22:30:50 -07002009#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002010 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2011 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002012 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07002013#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002014
Laurence Lundblade99615302020-11-29 11:19:47 -08002015 } else if(uTagToProcess == CBOR_TAG_MIME ||
2016 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002017 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002018
Laurence Lundblade99615302020-11-29 11:19:47 -08002019 } else {
2020 /* See if it is a pass-through byte/text string tag; process if so */
2021 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002022
Laurence Lundblade99615302020-11-29 11:19:47 -08002023 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2024 /* It wasn't a pass-through byte/text string tag so it is
2025 * an unknown tag. This is the exit from the loop on the
2026 * first unknown tag. It is a successful exit.
2027 */
2028 uReturn = QCBOR_SUCCESS;
2029 break;
2030 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002031 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002032
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002033 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002034 /* Error exit from the loop */
2035 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002036 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002037
2038 /* A tag was successfully processed, shift it out of the list of
2039 * tags returned. This is the loop increment.
2040 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002041 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002042 }
2043
2044Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002045 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002046}
2047
2048
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002049/*
2050 Public function, see header qcbor/qcbor_decode.h file
2051 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002052QCBORError
2053QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2054{
2055 QCBORError uErr;
2056 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2057 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002058 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2059 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2060 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002061 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002062}
2063
2064
2065/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002066 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002067 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002068QCBORError
2069QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2070{
2071 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2072 const UsefulInputBuf Save = pMe->InBuf;
2073
2074 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2075
2076 pMe->nesting = SaveNesting;
2077 pMe->InBuf = Save;
2078
2079 return uErr;
2080}
2081
2082
2083/*
2084 Public function, see header qcbor/qcbor_decode.h file
2085 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002086void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2087{
2088 if(pMe->uLastError != QCBOR_SUCCESS) {
2089 return;
2090 }
2091
2092 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2093}
2094
2095
2096/*
2097 Public function, see header qcbor/qcbor_decode.h file
2098 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002099QCBORError
2100QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2101 QCBORItem *pDecodedItem,
2102 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002103{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002104 QCBORError nReturn;
2105
2106 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2107 if(nReturn != QCBOR_SUCCESS) {
2108 return nReturn;
2109 }
2110
2111 if(pTags != NULL) {
2112 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002113 // Reverse the order because pTags is reverse of
2114 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002115 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2116 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002117 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002118 }
2119 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2120 return QCBOR_ERR_TOO_MANY_TAGS;
2121 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002122 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002123 pTags->uNumUsed++;
2124 }
2125 }
2126
2127 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002128}
2129
2130
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002131/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302132 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302133 next one down. If a layer has no work to do for a particular item
2134 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002135
Laurence Lundblade59289e52019-12-30 13:44:37 -08002136 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2137 tagged data items, turning them into the local C representation.
2138 For the most simple it is just associating a QCBOR_TYPE with the data. For
2139 the complex ones that an aggregate of data items, there is some further
2140 decoding and a little bit of recursion.
2141
2142 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302143 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302144 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002145 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002146
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302147 - GetNext_MapEntry -- This handles the combining of two
2148 items, the label and the data, that make up a map entry.
2149 It only does work on maps. It combines the label and data
2150 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002151
Laurence Lundblade59289e52019-12-30 13:44:37 -08002152 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2153 tags into bit flags associated with the data item. No actual decoding
2154 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002155
Laurence Lundblade59289e52019-12-30 13:44:37 -08002156 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302157 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302158 string allocater to create contiguous space for the item. It
2159 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002160
Laurence Lundblade59289e52019-12-30 13:44:37 -08002161 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2162 atomic data item has a "major type", an integer "argument" and optionally
2163 some content. For text and byte strings, the content is the bytes
2164 that make up the string. These are the smallest data items that are
2165 considered to be well-formed. The content may also be other data items in
2166 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002167
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002168 Roughly this takes 300 bytes of stack for vars. Need to
2169 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002170
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302171 */
2172
2173
2174/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002175 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002176 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002177bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002178 const QCBORItem *pItem,
2179 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002180{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002181 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2182 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002183 break;
2184 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002185 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002186 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002187 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002188 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002189
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002190 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002191}
2192
2193
2194/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002195 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002196 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002197QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002198{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002199 QCBORError uReturn = me->uLastError;
2200
2201 if(uReturn != QCBOR_SUCCESS) {
2202 goto Done;
2203 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002204
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002205 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002206 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002207 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002208 goto Done;
2209 }
2210
2211 // Error out if not all the bytes are consumed
2212 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002213 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002214 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002215
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002216Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002217#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade6de37062018-10-15 12:22:42 +05302218 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002219 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002220 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002221#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002222
Laurence Lundblade085d7952020-07-24 10:26:30 -07002223 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002224}
2225
2226
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002227/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002228 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002229*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002230// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002231uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2232 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002233 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002234{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002235 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2236 return CBOR_TAG_INVALID64;
2237 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002238 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2239 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002240 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002241 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002242 }
2243}
2244
Laurence Lundblade9b334962020-08-27 10:55:53 -07002245/*
2246 Public function, see header qcbor/qcbor_decode.h file
2247*/
2248uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2249 uint32_t uIndex)
2250{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002251 if(pMe->uLastError != QCBOR_SUCCESS) {
2252 return CBOR_TAG_INVALID64;
2253 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002254 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2255 return CBOR_TAG_INVALID64;
2256 } else {
2257 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2258 }
2259}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002260
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002261/*
2262
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002263Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002264
Laurence Lundbladeee851742020-01-08 08:37:05 -08002265 - Hit end of input before it was expected while decoding type and
2266 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002267
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002268 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002269
Laurence Lundbladeee851742020-01-08 08:37:05 -08002270 - Hit end of input while decoding a text or byte string
2271 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002272
Laurence Lundbladeee851742020-01-08 08:37:05 -08002273 - Encountered conflicting tags -- e.g., an item is tagged both a date
2274 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002275
Laurence Lundbladeee851742020-01-08 08:37:05 -08002276 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002277 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002278
Laurence Lundbladeee851742020-01-08 08:37:05 -08002279 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002280 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002281
Laurence Lundbladeee851742020-01-08 08:37:05 -08002282 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2283 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002284
Laurence Lundbladeee851742020-01-08 08:37:05 -08002285 - The type of a map label is not a string or int
2286 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002287
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002288 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002289
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002290 */
2291
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002292
2293
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002294#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002295
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002296/* ===========================================================================
2297 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002298
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002299 This implements a simple sting allocator for indefinite length
2300 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2301 implements the function type QCBORStringAllocate and allows easy
2302 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002303
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002304 This particular allocator is built-in for convenience. The caller
2305 can implement their own. All of this following code will get
2306 dead-stripped if QCBORDecode_SetMemPool() is not called.
2307
2308 This is a very primitive memory allocator. It does not track
2309 individual allocations, only a high-water mark. A free or
2310 reallocation must be of the last chunk allocated.
2311
2312 The size of the pool and offset to free memory are packed into the
2313 first 8 bytes of the memory pool so we don't have to keep them in
2314 the decode context. Since the address of the pool may not be
2315 aligned, they have to be packed and unpacked as if they were
2316 serialized data of the wire or such.
2317
2318 The sizes packed in are uint32_t to be the same on all CPU types
2319 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002320 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002321
2322
Laurence Lundbladeee851742020-01-08 08:37:05 -08002323static inline int
2324MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002325{
2326 // Use of UsefulInputBuf is overkill, but it is convenient.
2327 UsefulInputBuf UIB;
2328
Laurence Lundbladeee851742020-01-08 08:37:05 -08002329 // Just assume the size here. It was checked during SetUp so
2330 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002331 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002332 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2333 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2334 return UsefulInputBuf_GetError(&UIB);
2335}
2336
2337
Laurence Lundbladeee851742020-01-08 08:37:05 -08002338static inline int
2339MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002340{
2341 // Use of UsefulOutBuf is overkill, but convenient. The
2342 // length check performed here is useful.
2343 UsefulOutBuf UOB;
2344
2345 UsefulOutBuf_Init(&UOB, Pool);
2346 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2347 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2348 return UsefulOutBuf_GetError(&UOB);
2349}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002350
2351
2352/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002353 Internal function for an allocation, reallocation free and destuct.
2354
2355 Having only one function rather than one each per mode saves space in
2356 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002357
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002358 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2359 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002360static UsefulBuf
2361MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002362{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002363 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002364
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002365 uint32_t uPoolSize;
2366 uint32_t uFreeOffset;
2367
2368 if(uNewSize > UINT32_MAX) {
2369 // This allocator is only good up to 4GB. This check should
2370 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2371 goto Done;
2372 }
2373 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2374
2375 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2376 goto Done;
2377 }
2378
2379 if(uNewSize) {
2380 if(pMem) {
2381 // REALLOCATION MODE
2382 // Calculate pointer to the end of the memory pool. It is
2383 // assumed that pPool + uPoolSize won't wrap around by
2384 // assuming the caller won't pass a pool buffer in that is
2385 // not in legitimate memory space.
2386 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2387
2388 // Check that the pointer for reallocation is in the range of the
2389 // pool. This also makes sure that pointer math further down
2390 // doesn't wrap under or over.
2391 if(pMem >= pPool && pMem < pPoolEnd) {
2392 // Offset to start of chunk for reallocation. This won't
2393 // wrap under because of check that pMem >= pPool. Cast
2394 // is safe because the pool is always less than UINT32_MAX
2395 // because of check in QCBORDecode_SetMemPool().
2396 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2397
2398 // Check to see if the allocation will fit. uPoolSize -
2399 // uMemOffset will not wrap under because of check that
2400 // pMem is in the range of the uPoolSize by check above.
2401 if(uNewSize <= uPoolSize - uMemOffset) {
2402 ReturnValue.ptr = pMem;
2403 ReturnValue.len = uNewSize;
2404
2405 // Addition won't wrap around over because uNewSize was
2406 // checked to be sure it is less than the pool size.
2407 uFreeOffset = uMemOffset + uNewSize32;
2408 }
2409 }
2410 } else {
2411 // ALLOCATION MODE
2412 // uPoolSize - uFreeOffset will not underflow because this
2413 // pool implementation makes sure uFreeOffset is always
2414 // smaller than uPoolSize through this check here and
2415 // reallocation case.
2416 if(uNewSize <= uPoolSize - uFreeOffset) {
2417 ReturnValue.len = uNewSize;
2418 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002419 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002420 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002421 }
2422 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002423 if(pMem) {
2424 // FREE MODE
2425 // Cast is safe because of limit on pool size in
2426 // QCBORDecode_SetMemPool()
2427 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2428 } else {
2429 // DESTRUCT MODE
2430 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002431 }
2432 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002433
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002434 UsefulBuf Pool = {pPool, uPoolSize};
2435 MemPool_Pack(Pool, uFreeOffset);
2436
2437Done:
2438 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002439}
2440
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002441
Laurence Lundbladef6531662018-12-04 10:42:22 +09002442/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002443 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002444 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002445QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2446 UsefulBuf Pool,
2447 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002448{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002449 // The pool size and free mem offset are packed into the beginning
2450 // of the pool memory. This compile time check make sure the
2451 // constant in the header is correct. This check should optimize
2452 // down to nothing.
2453 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002454 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002455 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002456
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002457 // The pool size and free offset packed in to the beginning of pool
2458 // memory are only 32-bits. This check will optimize out on 32-bit
2459 // machines.
2460 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002461 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002462 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002463
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002464 // This checks that the pool buffer given is big enough.
2465 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002466 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002467 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002468
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002469 pMe->StringAllocator.pfAllocator = MemPool_Function;
2470 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2471 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002472
Laurence Lundblade30816f22018-11-10 13:40:22 +07002473 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002474}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002475#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002476
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002477
2478
Laurence Lundblade9b334962020-08-27 10:55:53 -07002479static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2480{
2481 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2482}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002483
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002484
2485/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002486 Consume an entire map or array (and do next to
2487 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002488 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002489static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002490ConsumeItem(QCBORDecodeContext *pMe,
2491 const QCBORItem *pItemToConsume,
2492 uint_fast8_t *puNextNestLevel)
2493{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002494 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002495 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002496
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002497 // If it is a map or array, this will tell if it is empty.
2498 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2499
2500 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2501 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002502
Laurence Lundblade1341c592020-04-11 14:19:05 -07002503 /* This works for definite and indefinite length
2504 * maps and arrays by using the nesting level
2505 */
2506 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002507 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002508 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002509 goto Done;
2510 }
2511 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002512
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002513 *puNextNestLevel = Item.uNextNestLevel;
2514
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002515 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002516
Laurence Lundblade1341c592020-04-11 14:19:05 -07002517 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002518 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002519 /* Just pass the nesting level through */
2520 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2521
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002522 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002523 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002524
2525Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002526 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002527}
2528
2529
Laurence Lundblade1341c592020-04-11 14:19:05 -07002530/* Return true if the labels in Item1 and Item2 are the same.
2531 Works only for integer and string labels. Returns false
2532 for any other type. */
2533static inline bool
2534MatchLabel(QCBORItem Item1, QCBORItem Item2)
2535{
2536 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2537 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2538 return true;
2539 }
2540 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002541 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002542 return true;
2543 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002544 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002545 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2546 return true;
2547 }
2548 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2549 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2550 return true;
2551 }
2552 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002553
Laurence Lundblade1341c592020-04-11 14:19:05 -07002554 /* Other label types are never matched */
2555 return false;
2556}
2557
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002558
2559/*
2560 Returns true if Item1 and Item2 are the same type
2561 or if either are of QCBOR_TYPE_ANY.
2562 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002563static inline bool
2564MatchType(QCBORItem Item1, QCBORItem Item2)
2565{
2566 if(Item1.uDataType == Item2.uDataType) {
2567 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002568 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002569 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002570 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002571 return true;
2572 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002573 return false;
2574}
2575
2576
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002577/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002578 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002579
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002580 @param[in] pMe The decode context to search.
2581 @param[in,out] pItemArray The items to search for and the items found.
2582 @param[out] puOffset Byte offset of last item matched.
2583 @param[in] pCBContext Context for the not-found item call back.
2584 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002585
2586 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2587
Laurence Lundblade93d89472020-10-03 22:30:50 -07002588 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2589 were found for one of the labels being
2590 search for. This duplicate detection is
2591 only performed for items in pItemArray,
2592 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002593
Laurence Lundblade93d89472020-10-03 22:30:50 -07002594 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2595 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002596
2597 @retval Also errors returned by QCBORDecode_GetNext().
2598
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002599 On input pItemArray contains a list of labels and data types
2600 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002601
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002602 On output the fully retrieved items are filled in with
2603 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002604
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002605 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002606
2607 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002608 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002609static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002610MapSearch(QCBORDecodeContext *pMe,
2611 QCBORItem *pItemArray,
2612 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002613 void *pCBContext,
2614 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002615{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002616 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002617 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002618
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002619 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002620 uReturn = pMe->uLastError;
2621 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002622 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002623
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002624 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002625 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2626 /* QCBOR_TYPE_NONE as first item indicates just looking
2627 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002628 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2629 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002630 }
2631
Laurence Lundblade085d7952020-07-24 10:26:30 -07002632 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2633 // It is an empty bounded array or map
2634 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2635 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002636 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002637 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002638 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002639 // Nothing is ever found in an empty array or map. All items
2640 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002641 uReturn = QCBOR_SUCCESS;
2642 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002643 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002644 }
2645
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002646 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002647 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2648
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002649 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002650 UsefulInputBuf_Seek(&(pMe->InBuf),
2651 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002652
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002653 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002654 Loop over all the items in the map or array. Each item
2655 could be a map or array, but label matching is only at
2656 the main level. This handles definite and indefinite
2657 length maps and arrays. The only reason this is ever
2658 called on arrays is to find their end position.
2659
2660 This will always run over all items in order to do
2661 duplicate detection.
2662
2663 This will exit with failure if it encounters an
2664 unrecoverable error, but continue on for recoverable
2665 errors.
2666
2667 If a recoverable error occurs on a matched item, then
2668 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002669 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002670 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002671 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002672 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002673 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002674 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002675
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002676 /* Get the item */
2677 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002678 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2679 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002680 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002681 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002682 goto Done;
2683 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002684 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002685 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002686 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002687 goto Done;
2688 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002689
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002690 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002691 bool bMatched = false;
2692 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2693 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002694 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002695 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2696 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002697 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002698 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002699 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002700 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002701 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002702 goto Done;
2703 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002704
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002705 if(uResult != QCBOR_SUCCESS) {
2706 uReturn = uResult;
2707 goto Done;
2708 }
2709
Laurence Lundblade1341c592020-04-11 14:19:05 -07002710 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002711 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002712 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002713 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002714 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002715 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002716 bMatched = true;
2717 }
2718 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002719
2720
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002721 if(!bMatched && pfCallback != NULL) {
2722 /*
2723 Call the callback on unmatched labels.
2724 (It is tempting to do duplicate detection here, but that would
2725 require dynamic memory allocation because the number of labels
2726 that might be encountered is unbounded.)
2727 */
2728 uReturn = (*pfCallback)(pCBContext, &Item);
2729 if(uReturn != QCBOR_SUCCESS) {
2730 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002731 }
2732 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002733
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002734 /*
2735 Consume the item whether matched or not. This
2736 does the work of traversing maps and array and
2737 everything in them. In this loop only the
2738 items at the current nesting level are examined
2739 to match the labels.
2740 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002741 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002742 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002743 goto Done;
2744 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002745
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002746 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002747
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002748 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002749
2750 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002751
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002752 // Check here makes sure that this won't accidentally be
2753 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002754 // QCBOR_MAX_DECODE_INPUT_SIZE.
2755 if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
2756 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2757 goto Done;
2758 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002759 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2760 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002761
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002762 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002763 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2764
2765 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002766 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002767 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002768 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002769 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2770 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002771 }
2772 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002773
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002774 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002775}
2776
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002777
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002778/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002779 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002780*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002781void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2782 int64_t nLabel,
2783 uint8_t uQcborType,
2784 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002785{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002786 if(pMe->uLastError != QCBOR_SUCCESS) {
2787 return;
2788 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002789
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002790 QCBORItem OneItemSeach[2];
2791 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2792 OneItemSeach[0].label.int64 = nLabel;
2793 OneItemSeach[0].uDataType = uQcborType;
2794 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002795
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002796 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002797
2798 *pItem = OneItemSeach[0];
2799
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002800 if(uReturn != QCBOR_SUCCESS) {
2801 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002802 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002803 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002804 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002805 }
2806
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002807 Done:
2808 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002809}
2810
2811
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002812/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002813 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002814*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002815void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2816 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002817 uint8_t uQcborType,
2818 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002819{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002820 if(pMe->uLastError != QCBOR_SUCCESS) {
2821 return;
2822 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002823
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002824 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002825 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2826 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2827 OneItemSeach[0].uDataType = uQcborType;
2828 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002829
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002830 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2831 if(uReturn != QCBOR_SUCCESS) {
2832 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002833 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002834 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002835 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002836 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002837 }
2838
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002839 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002840
2841Done:
2842 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002843}
2844
2845
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002846
Laurence Lundblade93d89472020-10-03 22:30:50 -07002847static QCBORError
2848CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002849{
2850 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2851 if(uDataType == puTypeList[i]) {
2852 return QCBOR_SUCCESS;
2853 }
2854 }
2855 return QCBOR_ERR_UNEXPECTED_TYPE;
2856}
2857
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002858
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002859/**
2860 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002861 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002862
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002863 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2864 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002865
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002866 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2867 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002868 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002869static QCBORError
2870CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002871{
2872 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2873 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2874 /* There are tags that QCBOR couldn't process on this item and
2875 the caller has told us there should not be. */
2876 return QCBOR_ERR_UNEXPECTED_TYPE;
2877 }
2878
2879 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2880 const int nItemType = pItem->uDataType;
2881
2882 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2883 // Must match the tag and only the tag
2884 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2885 }
2886
2887 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2888 if(uReturn == QCBOR_SUCCESS) {
2889 return QCBOR_SUCCESS;
2890 }
2891
2892 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2893 /* Must match the content type and only the content type.
2894 There was no match just above so it is a fail. */
2895 return QCBOR_ERR_UNEXPECTED_TYPE;
2896 }
2897
2898 /* If here it can match either the tag or the content
2899 and it hasn't matched the content, so the end
2900 result is whether it matches the tag. This is
2901 also the case that the CBOR standard discourages. */
2902
2903 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2904}
2905
Laurence Lundblade9b334962020-08-27 10:55:53 -07002906
Laurence Lundblade9b334962020-08-27 10:55:53 -07002907
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002908// This could be semi-private if need be
2909static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002910void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2911 int64_t nLabel,
2912 TagSpecification TagSpec,
2913 QCBORItem *pItem)
2914{
2915 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2916 if(pMe->uLastError != QCBOR_SUCCESS) {
2917 return;
2918 }
2919
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002920 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002921}
2922
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002923
2924// This could be semi-private if need be
2925static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002926void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2927 const char *szLabel,
2928 TagSpecification TagSpec,
2929 QCBORItem *pItem)
2930{
2931 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2932 if(pMe->uLastError != QCBOR_SUCCESS) {
2933 return;
2934 }
2935
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002936 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002937}
2938
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002939// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002940void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2941 int64_t nLabel,
2942 TagSpecification TagSpec,
2943 UsefulBufC *pString)
2944{
2945 QCBORItem Item;
2946 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2947 if(pMe->uLastError == QCBOR_SUCCESS) {
2948 *pString = Item.val.string;
2949 }
2950}
2951
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002952// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002953void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2954 const char * szLabel,
2955 TagSpecification TagSpec,
2956 UsefulBufC *pString)
2957{
2958 QCBORItem Item;
2959 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2960 if(pMe->uLastError == QCBOR_SUCCESS) {
2961 *pString = Item.val.string;
2962 }
2963}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002964
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002965/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002966 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002967*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002968void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002969{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002970 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2971 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002972}
2973
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002974/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002975 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002976*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002977void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2978 QCBORItem *pItemList,
2979 void *pCallbackCtx,
2980 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002981{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002982 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2983 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002984}
2985
2986
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08002987/**
2988 * @brief Search for a map/array by label and enter it
2989 *
2990 * @param[in] pMe The decode context.
2991 * @param[in] pSearch The map/array to search for.
2992 *
2993 * @c pSearch is expected to contain one item of type map or array
2994 * with the label specified. The current bounded map will be searched for
2995 * this and if found will be entered.
2996 *
2997 * If the label is not found, or the item found is not a map or array,
2998 * the error state is set.
2999 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003000static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003001{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003002 // The first item in pSearch is the one that is to be
3003 // entered. It should be the only one filled in. Any other
3004 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003005 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003006 return;
3007 }
3008
3009 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003010 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003011 if(pMe->uLastError != QCBOR_SUCCESS) {
3012 return;
3013 }
3014
Laurence Lundblade9b334962020-08-27 10:55:53 -07003015 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003016 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003017 return;
3018 }
3019
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003020 /*
3021 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3022 * next item for the pre-order traversal cursor to be the map/array
3023 * found by MapSearch(). The next few lines of code force the
3024 * cursor to that.
3025 *
3026 * There is no need to retain the old cursor because
3027 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3028 * beginning of the map/array being entered.
3029 *
3030 * The cursor is forced by: 1) setting the input buffer position to
3031 * the item offset found by MapSearch(), 2) setting the map/array
3032 * counter to the total in the map/array, 3) setting the nesting
3033 * level. Setting the map/array counter to the total is not
3034 * strictly correct, but this is OK because this cursor only needs
3035 * to be used to get one item and MapSearch() has already found it
3036 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003037 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003038 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003039
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003040 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3041
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003042 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003043
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003044 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003045}
3046
3047
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003048/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003049 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003050*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003051void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003052{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003053 QCBORItem OneItemSeach[2];
3054 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3055 OneItemSeach[0].label.int64 = nLabel;
3056 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3057 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003058
Laurence Lundblade9b334962020-08-27 10:55:53 -07003059 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003060 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003061}
3062
3063
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003064/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003065 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003066*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003067void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003068{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003069 QCBORItem OneItemSeach[2];
3070 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3071 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3072 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3073 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003074
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003075 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003076}
3077
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003078/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003079 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003080*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003081void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003082{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003083 QCBORItem OneItemSeach[2];
3084 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3085 OneItemSeach[0].label.int64 = nLabel;
3086 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3087 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003088
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003089 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003090}
3091
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003092/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003093 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003094*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003095void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3096{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003097 QCBORItem OneItemSeach[2];
3098 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3099 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3100 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3101 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003102
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003103 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003104}
3105
3106
Laurence Lundblade02625d42020-06-25 14:41:41 -07003107// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003108void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003109{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003110 QCBORError uErr;
3111
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003112 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003113 if(pMe->uLastError != QCBOR_SUCCESS) {
3114 // Already in error state; do nothing.
3115 return;
3116 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003117
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003118 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003119 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003120 uErr = QCBORDecode_GetNext(pMe, &Item);
3121 if(uErr != QCBOR_SUCCESS) {
3122 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003123 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003124 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003125 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3126 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003127 }
3128
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003129 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003130
3131
Laurence Lundbladef0499502020-08-01 11:55:57 -07003132 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003133 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003134 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3135 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003136 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003137 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3138 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003139 // Special case to increment nesting level for zero-length maps
3140 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003141 DecodeNesting_Descend(&(pMe->nesting), uType);
3142 }
3143
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003144 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003145
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003146 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3147 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003148
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003149 if(pItem != NULL) {
3150 *pItem = Item;
3151 }
3152
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003153Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003154 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003155}
3156
Laurence Lundblade02625d42020-06-25 14:41:41 -07003157
3158/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003159 This is the common work for exiting a level that is a bounded map,
3160 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003161
3162 One chunk of work is to set up the pre-order traversal so it is at
3163 the item just after the bounded map, array or bstr that is being
3164 exited. This is somewhat complex.
3165
3166 The other work is to level-up the bounded mode to next higest bounded
3167 mode or the top level if there isn't one.
3168 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003169static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003170ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003171{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003172 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003173
Laurence Lundblade02625d42020-06-25 14:41:41 -07003174 /*
3175 First the pre-order-traversal byte offset is positioned to the
3176 item just after the bounded mode item that was just consumed.
3177 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003178 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3179
Laurence Lundblade02625d42020-06-25 14:41:41 -07003180 /*
3181 Next, set the current nesting level to one above the bounded level
3182 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003183
Laurence Lundblade02625d42020-06-25 14:41:41 -07003184 DecodeNesting_CheckBoundedType() is always called before this and
3185 makes sure pCurrentBounded is valid.
3186 */
3187 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3188
3189 /*
3190 This does the complex work of leveling up the pre-order traversal
3191 when the end of a map or array or another bounded level is
3192 reached. It may do nothing, or ascend all the way to the top
3193 level.
3194 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003195 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003196 if(uErr != QCBOR_SUCCESS) {
3197 goto Done;
3198 }
3199
Laurence Lundblade02625d42020-06-25 14:41:41 -07003200 /*
3201 This makes the next highest bounded level the current bounded
3202 level. If there is no next highest level, then no bounded mode is
3203 in effect.
3204 */
3205 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003206
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003207 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003208
3209Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003210 return uErr;
3211}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003212
Laurence Lundblade02625d42020-06-25 14:41:41 -07003213
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003214// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003215void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003216{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003217 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003218 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003219 return;
3220 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003221
Laurence Lundblade02625d42020-06-25 14:41:41 -07003222 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003223
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003224 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003225 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003226 goto Done;
3227 }
3228
Laurence Lundblade02625d42020-06-25 14:41:41 -07003229 /*
3230 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003231 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003232 from previous map search, then do a dummy search.
3233 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003234 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003235 QCBORItem Dummy;
3236 Dummy.uLabelType = QCBOR_TYPE_NONE;
3237 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3238 if(uErr != QCBOR_SUCCESS) {
3239 goto Done;
3240 }
3241 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003242
Laurence Lundblade02625d42020-06-25 14:41:41 -07003243 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003244
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003245Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003246 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003247}
3248
3249
Laurence Lundblade1341c592020-04-11 14:19:05 -07003250
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003251static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003252 const QCBORItem *pItem,
3253 uint8_t uTagRequirement,
3254 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003255{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003256 if(pBstr) {
3257 *pBstr = NULLUsefulBufC;
3258 }
3259
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003260 if(pMe->uLastError != QCBOR_SUCCESS) {
3261 // Already in error state; do nothing.
3262 return pMe->uLastError;
3263 }
3264
3265 QCBORError uError = QCBOR_SUCCESS;
3266
3267 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3268 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3269 goto Done;;
3270 }
3271
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003272 const TagSpecification TagSpec =
3273 {
3274 uTagRequirement,
3275 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3276 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3277 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003278
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003279 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003280 if(uError != QCBOR_SUCCESS) {
3281 goto Done;
3282 }
3283
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003284 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003285 // Reverse the decrement done by GetNext() for the bstr so the
3286 // increment in NestLevelAscender() called by ExitBoundedLevel()
3287 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003288 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003289 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003290
3291 if(pBstr) {
3292 *pBstr = pItem->val.string;
3293 }
3294
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003295 // This saves the current length of the UsefulInputBuf and then
3296 // narrows the UsefulInputBuf to start and length of the wrapped
3297 // CBOR that is being entered.
3298 //
3299 // This makes sure the length is less than
3300 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3301 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3302 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3303 // the casts safe. uEndOfBstr will always be less than
3304 // uPreviousLength because of the way UsefulInputBuf works so there
3305 // is no need to check it. There is also a range check in the
3306 // seek.
3307 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003308 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003309 // amount to much code.
3310 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3311 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003312 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003313 goto Done;
3314 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003315 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003316 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003317 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003318
Laurence Lundblade02625d42020-06-25 14:41:41 -07003319 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003320 (uint32_t)uPreviousLength,
3321 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003322Done:
3323 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003324}
3325
3326
Laurence Lundblade02625d42020-06-25 14:41:41 -07003327/*
3328 Public function, see header qcbor/qcbor_decode.h file
3329 */
3330void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003331 uint8_t uTagRequirement,
3332 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003333{
3334 if(pMe->uLastError != QCBOR_SUCCESS) {
3335 // Already in error state; do nothing.
3336 return;
3337 }
3338
3339 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003340 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003341 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3342 if(pMe->uLastError != QCBOR_SUCCESS) {
3343 return;
3344 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003345
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003346 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003347 &Item,
3348 uTagRequirement,
3349 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003350}
3351
3352
Laurence Lundblade02625d42020-06-25 14:41:41 -07003353/*
3354 Public function, see header qcbor/qcbor_decode.h file
3355 */
3356void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003357 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003358 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003359 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003360{
3361 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003362 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003363
Laurence Lundblade93d89472020-10-03 22:30:50 -07003364 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3365 &Item,
3366 uTagRequirement,
3367 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003368}
3369
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003370
Laurence Lundblade02625d42020-06-25 14:41:41 -07003371/*
3372 Public function, see header qcbor/qcbor_decode.h file
3373 */
3374void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003375 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003376 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003377 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003378{
3379 QCBORItem Item;
3380 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3381
Laurence Lundblade93d89472020-10-03 22:30:50 -07003382 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3383 &Item,
3384 uTagRequirement,
3385 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003386}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003387
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003388
Laurence Lundblade02625d42020-06-25 14:41:41 -07003389/*
3390 Public function, see header qcbor/qcbor_decode.h file
3391 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003392void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003393{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003394 if(pMe->uLastError != QCBOR_SUCCESS) {
3395 // Already in error state; do nothing.
3396 return;
3397 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003398
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003399 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003400 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003401 return;
3402 }
3403
3404 /*
3405 Reset the length of the UsefulInputBuf to what it was before
3406 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003407 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003408 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003409 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003410
3411
Laurence Lundblade02625d42020-06-25 14:41:41 -07003412 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003413 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003414}
3415
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003416
Laurence Lundbladee6430642020-03-14 21:15:44 -07003417
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003418
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003419
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003420
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003421
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003422
Laurence Lundblade93d89472020-10-03 22:30:50 -07003423static QCBORError
3424InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003425{
3426 switch(pItem->uDataType) {
3427 case QCBOR_TYPE_TRUE:
3428 *pBool = true;
3429 return QCBOR_SUCCESS;
3430 break;
3431
3432 case QCBOR_TYPE_FALSE:
3433 *pBool = false;
3434 return QCBOR_SUCCESS;
3435 break;
3436
3437 default:
3438 return QCBOR_ERR_UNEXPECTED_TYPE;
3439 break;
3440 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003441 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003442}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003443
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003444
Laurence Lundblade9b334962020-08-27 10:55:53 -07003445
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003446/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003447 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003448*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003449void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003450{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003451 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003452 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003453 return;
3454 }
3455
Laurence Lundbladec4537442020-04-14 18:53:22 -07003456 QCBORError nError;
3457 QCBORItem Item;
3458
3459 nError = QCBORDecode_GetNext(pMe, &Item);
3460 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003461 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003462 return;
3463 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003464 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003465}
3466
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003467
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003468/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003469 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003470*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003471void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003472{
3473 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003474 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003475
Laurence Lundblade9b334962020-08-27 10:55:53 -07003476 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003477}
3478
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003479
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003480/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003481 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003482*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003483void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3484{
3485 QCBORItem Item;
3486 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3487
Laurence Lundblade9b334962020-08-27 10:55:53 -07003488 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003489}
3490
3491
3492
Laurence Lundbladec7114722020-08-13 05:11:40 -07003493
3494static void ProcessEpochDate(QCBORDecodeContext *pMe,
3495 QCBORItem *pItem,
3496 uint8_t uTagRequirement,
3497 int64_t *pnTime)
3498{
3499 if(pMe->uLastError != QCBOR_SUCCESS) {
3500 // Already in error state, do nothing
3501 return;
3502 }
3503
3504 QCBORError uErr;
3505
3506 const TagSpecification TagSpec =
3507 {
3508 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003509 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3510 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003511 };
3512
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003513 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003514 if(uErr != QCBOR_SUCCESS) {
3515 goto Done;
3516 }
3517
3518 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3519 uErr = DecodeDateEpoch(pItem);
3520 if(uErr != QCBOR_SUCCESS) {
3521 goto Done;
3522 }
3523 }
3524
Laurence Lundblade9b334962020-08-27 10:55:53 -07003525 // Save the tags in the last item's tags in the decode context
3526 // for QCBORDecode_GetNthTagOfLast()
3527 CopyTags(pMe, pItem);
3528
Laurence Lundbladec7114722020-08-13 05:11:40 -07003529 *pnTime = pItem->val.epochDate.nSeconds;
3530
3531Done:
3532 pMe->uLastError = (uint8_t)uErr;
3533}
3534
3535
3536void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003537 uint8_t uTagRequirement,
3538 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003539{
3540 if(pMe->uLastError != QCBOR_SUCCESS) {
3541 // Already in error state, do nothing
3542 return;
3543 }
3544
3545 QCBORItem Item;
3546 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3547
3548 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3549}
3550
3551
3552void
3553QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3554 int64_t nLabel,
3555 uint8_t uTagRequirement,
3556 int64_t *pnTime)
3557{
3558 QCBORItem Item;
3559 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3560 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3561}
3562
3563
3564void
3565QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3566 const char *szLabel,
3567 uint8_t uTagRequirement,
3568 int64_t *pnTime)
3569{
3570 QCBORItem Item;
3571 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3572 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3573}
3574
3575
3576
3577
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003578void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3579 TagSpecification TagSpec,
3580 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003581{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003582 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003583 // Already in error state, do nothing
3584 return;
3585 }
3586
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003587 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003588 QCBORItem Item;
3589
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003590 uError = QCBORDecode_GetNext(pMe, &Item);
3591 if(uError != QCBOR_SUCCESS) {
3592 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003593 return;
3594 }
3595
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003596 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003597
3598 if(pMe->uLastError == QCBOR_SUCCESS) {
3599 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003600 } else {
3601 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003602 }
3603}
3604
Laurence Lundbladec4537442020-04-14 18:53:22 -07003605
3606
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003607
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003608static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003609 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003610 UsefulBufC *pValue,
3611 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003612{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003613 const TagSpecification TagSpec =
3614 {
3615 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003616 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3617 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003618 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003619
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003620 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003621 if(uErr != QCBOR_SUCCESS) {
3622 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003623 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003624
3625 *pValue = pItem->val.string;
3626
3627 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3628 *pbIsNegative = false;
3629 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3630 *pbIsNegative = true;
3631 }
3632
3633 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003634}
3635
3636
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003637/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003638 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003639 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003640void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3641 uint8_t uTagRequirement,
3642 UsefulBufC *pValue,
3643 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003644{
3645 if(pMe->uLastError != QCBOR_SUCCESS) {
3646 // Already in error state, do nothing
3647 return;
3648 }
3649
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003650 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003651 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3652 if(uError != QCBOR_SUCCESS) {
3653 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003654 return;
3655 }
3656
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003657 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003658}
3659
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003660
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003661/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003662 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003663*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003664void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3665 int64_t nLabel,
3666 uint8_t uTagRequirement,
3667 UsefulBufC *pValue,
3668 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003669{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003670 QCBORItem Item;
3671 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003672 if(pMe->uLastError != QCBOR_SUCCESS) {
3673 return;
3674 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003675
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003676 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003677}
3678
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003679
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003680/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003681 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003682*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003683void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3684 const char *szLabel,
3685 uint8_t uTagRequirement,
3686 UsefulBufC *pValue,
3687 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003688{
3689 QCBORItem Item;
3690 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003691 if(pMe->uLastError != QCBOR_SUCCESS) {
3692 return;
3693 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003694
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003695 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003696}
3697
3698
3699
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003700
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003701// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003702QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3703 const QCBORItem *pItem,
3704 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003705 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003706{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003707 const TagSpecification TagSpecText =
3708 {
3709 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003710 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3711 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003712 };
3713 const TagSpecification TagSpecBinary =
3714 {
3715 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003716 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3717 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003718 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003719
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003720 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003721
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003722 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003723 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003724 if(pbIsTag257 != NULL) {
3725 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003726 }
3727 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003728 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003729 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003730 if(pbIsTag257 != NULL) {
3731 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003732 }
3733 uReturn = QCBOR_SUCCESS;
3734
3735 } else {
3736 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3737 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003738
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003739 return uReturn;
3740}
3741
Laurence Lundblade93d89472020-10-03 22:30:50 -07003742// Improvement: add methods for wrapped CBOR, a simple alternate
3743// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003744
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003745
3746
3747
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003748#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003749
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003750typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003751
3752
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003753// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003754static QCBORError
3755Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003756{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003757 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003758
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003759 if(uResult != 0) {
3760 /* This loop will run a maximum of 19 times because
3761 * UINT64_MAX < 10 ^^ 19. More than that will cause
3762 * exit with the overflow error
3763 */
3764 for(; nExponent > 0; nExponent--) {
3765 if(uResult > UINT64_MAX / 10) {
3766 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3767 }
3768 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003769 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003770
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003771 for(; nExponent < 0; nExponent++) {
3772 uResult = uResult / 10;
3773 if(uResult == 0) {
3774 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3775 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003776 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003777 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003778 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003779
3780 *puResult = uResult;
3781
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003782 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003783}
3784
3785
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003786// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003787static QCBORError
3788Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003789{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003790 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003791
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003792 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003793
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003794 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003795 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003796 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003797 */
3798 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003799 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003800 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003801 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003802 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003803 nExponent--;
3804 }
3805
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003806 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003807 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003808 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3809 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003810 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003811 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003812 }
3813
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003814 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003815
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003816 return QCBOR_SUCCESS;
3817}
3818
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003819
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003820/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003821 Compute value with signed mantissa and signed result. Works with
3822 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003823 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003824static inline QCBORError ExponentiateNN(int64_t nMantissa,
3825 int64_t nExponent,
3826 int64_t *pnResult,
3827 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003828{
3829 uint64_t uResult;
3830
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003831 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003832 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003833 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3834
3835 // Do the exponentiation of the positive mantissa
3836 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3837 if(uReturn) {
3838 return uReturn;
3839 }
3840
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003841
Laurence Lundblade983500d2020-05-14 11:49:34 -07003842 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3843 of INT64_MIN. This assumes two's compliment representation where
3844 INT64_MIN is one increment farther from 0 than INT64_MAX.
3845 Trying to write -INT64_MIN doesn't work to get this because the
3846 compiler tries to work with an int64_t which can't represent
3847 -INT64_MIN.
3848 */
3849 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3850
3851 // Error out if too large
3852 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003853 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3854 }
3855
3856 // Casts are safe because of checks above
3857 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3858
3859 return QCBOR_SUCCESS;
3860}
3861
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003862
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003863/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003864 Compute value with signed mantissa and unsigned result. Works with
3865 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003866 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003867static inline QCBORError ExponentitateNU(int64_t nMantissa,
3868 int64_t nExponent,
3869 uint64_t *puResult,
3870 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003871{
3872 if(nMantissa < 0) {
3873 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3874 }
3875
3876 // Cast to unsigned is OK because of check for negative
3877 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3878 // Exponentiation is straight forward
3879 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3880}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003881
3882
3883/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003884 Compute value with signed mantissa and unsigned result. Works with
3885 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003886 */
3887static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3888 int64_t nExponent,
3889 uint64_t *puResult,
3890 fExponentiator pfExp)
3891{
3892 return (*pfExp)(uMantissa, nExponent, puResult);
3893}
3894
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003895#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3896
3897
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003898
3899
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003900
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003901static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003902{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003903 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003904
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003905 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003906 const uint8_t *pByte = BigNum.ptr;
3907 size_t uLen = BigNum.len;
3908 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003909 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003910 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003911 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003912 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003913 }
3914
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003915 *pResult = uResult;
3916 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003917}
3918
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003919
Laurence Lundblade887add82020-05-17 05:50:34 -07003920static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003921{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003922 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003923}
3924
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003925
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003926static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003927{
3928 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003929 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3930 if(uError) {
3931 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003932 }
3933 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3934 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003935 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003936}
3937
3938
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003939static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003940{
3941 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003942 /* The negative integer furthest from zero for a C int64_t is
3943 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3944 negative number in CBOR is computed as -n - 1 where n is the
3945 encoded integer, where n is what is in the variable BigNum. When
3946 converting BigNum to a uint64_t, the maximum value is thus
3947 INT64_MAX, so that when it -n - 1 is applied to it the result will
3948 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003949
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003950 -n - 1 <= INT64_MIN.
3951 -n - 1 <= -INT64_MAX - 1
3952 n <= INT64_MAX.
3953 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003954 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003955 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003956 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003957 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003958
3959 /// Now apply -n - 1. The cast is safe because
3960 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3961 // is the largest positive integer that an int64_t can
3962 // represent. */
3963 *pnResult = -(int64_t)uResult - 1;
3964
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003965 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003966}
3967
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003968
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003969
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003970
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003971
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003972/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003973Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003974
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003975\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003976
Laurence Lundblade93d89472020-10-03 22:30:50 -07003977\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
3978 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003979
3980\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3981
Laurence Lundblade93d89472020-10-03 22:30:50 -07003982\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
3983 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003984*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07003985static QCBORError
3986ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003987{
3988 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003989 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003990 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003991#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003992 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003993 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3994 http://www.cplusplus.com/reference/cmath/llround/
3995 */
3996 // Not interested in FE_INEXACT
3997 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003998 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3999 *pnValue = llround(pItem->val.dfnum);
4000 } else {
4001 *pnValue = lroundf(pItem->val.fnum);
4002 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004003 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4004 // llround() shouldn't result in divide by zero, but catch
4005 // it here in case it unexpectedly does. Don't try to
4006 // distinguish between the various exceptions because it seems
4007 // they vary by CPU, compiler and OS.
4008 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004009 }
4010 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004011 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004012 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004013#else
4014 return QCBOR_ERR_HW_FLOAT_DISABLED;
4015#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004016 break;
4017
4018 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004019 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004020 *pnValue = pItem->val.int64;
4021 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004022 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004023 }
4024 break;
4025
4026 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004027 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004028 if(pItem->val.uint64 < INT64_MAX) {
4029 *pnValue = pItem->val.int64;
4030 } else {
4031 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4032 }
4033 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004034 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004035 }
4036 break;
4037
4038 default:
4039 return QCBOR_ERR_UNEXPECTED_TYPE;
4040 }
4041 return QCBOR_SUCCESS;
4042}
4043
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004044
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004045void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004046 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004047 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004048 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004049{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004050 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004051 return;
4052 }
4053
Laurence Lundbladee6430642020-03-14 21:15:44 -07004054 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004055 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4056 if(uError) {
4057 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004058 return;
4059 }
4060
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004061 if(pItem) {
4062 *pItem = Item;
4063 }
4064
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004065 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004066}
4067
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004068
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004069void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4070 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004071 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004072 int64_t *pnValue,
4073 QCBORItem *pItem)
4074{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004075 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004076 if(pMe->uLastError != QCBOR_SUCCESS) {
4077 return;
4078 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004079
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004080 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004081}
4082
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004083
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004084void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4085 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004086 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004087 int64_t *pnValue,
4088 QCBORItem *pItem)
4089{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004090 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004091 if(pMe->uLastError != QCBOR_SUCCESS) {
4092 return;
4093 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004094
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004095 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004096}
4097
4098
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004099/*
4100 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004101
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004102 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004103
Laurence Lundblade93d89472020-10-03 22:30:50 -07004104 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4105 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004106
4107 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4108
Laurence Lundblade93d89472020-10-03 22:30:50 -07004109 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4110 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004111 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004112static QCBORError
4113Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004114{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004115 switch(pItem->uDataType) {
4116
4117 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004118 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004119 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004120 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004121 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004122 }
4123 break;
4124
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004125 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004126 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004127 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004128 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004129 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004130 }
4131 break;
4132
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004133#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4134 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004135 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004136 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004137 pItem->val.expAndMantissa.nExponent,
4138 pnValue,
4139 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004140 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004141 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004142 }
4143 break;
4144
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004145 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004146 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004147 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004148 pItem->val.expAndMantissa.nExponent,
4149 pnValue,
4150 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004151 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004152 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004153 }
4154 break;
4155
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004156 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004157 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004158 int64_t nMantissa;
4159 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004160 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4161 if(uErr) {
4162 return uErr;
4163 }
4164 return ExponentiateNN(nMantissa,
4165 pItem->val.expAndMantissa.nExponent,
4166 pnValue,
4167 Exponentitate10);
4168 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004169 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004170 }
4171 break;
4172
4173 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004174 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004175 int64_t nMantissa;
4176 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004177 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4178 if(uErr) {
4179 return uErr;
4180 }
4181 return ExponentiateNN(nMantissa,
4182 pItem->val.expAndMantissa.nExponent,
4183 pnValue,
4184 Exponentitate10);
4185 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004186 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004187 }
4188 break;
4189
4190 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004191 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004192 int64_t nMantissa;
4193 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004194 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4195 if(uErr) {
4196 return uErr;
4197 }
4198 return ExponentiateNN(nMantissa,
4199 pItem->val.expAndMantissa.nExponent,
4200 pnValue,
4201 Exponentitate2);
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 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004208 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004209 int64_t nMantissa;
4210 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004211 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4212 if(uErr) {
4213 return uErr;
4214 }
4215 return ExponentiateNN(nMantissa,
4216 pItem->val.expAndMantissa.nExponent,
4217 pnValue,
4218 Exponentitate2);
4219 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004220 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004221 }
4222 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004223#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4224
Laurence Lundbladee6430642020-03-14 21:15:44 -07004225
Laurence Lundbladec4537442020-04-14 18:53:22 -07004226 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004227 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004228}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004229
4230
Laurence Lundbladec4537442020-04-14 18:53:22 -07004231/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004232 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004233 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004234void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004235{
4236 QCBORItem Item;
4237
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004238 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004239
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004240 if(pMe->uLastError == QCBOR_SUCCESS) {
4241 // The above conversion succeeded
4242 return;
4243 }
4244
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004245 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004246 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004247 return;
4248 }
4249
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004250 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004251}
4252
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004253
4254/*
4255Public function, see header qcbor/qcbor_decode.h file
4256*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004257void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4258 int64_t nLabel,
4259 uint32_t uConvertTypes,
4260 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004261{
4262 QCBORItem Item;
4263
Laurence Lundblade93d89472020-10-03 22:30:50 -07004264 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4265 nLabel,
4266 uConvertTypes,
4267 pnValue,
4268 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004269
4270 if(pMe->uLastError == QCBOR_SUCCESS) {
4271 // The above conversion succeeded
4272 return;
4273 }
4274
4275 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4276 // The above conversion failed in a way that code below can't correct
4277 return;
4278 }
4279
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004280 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004281}
4282
4283
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004284/*
4285Public function, see header qcbor/qcbor_decode.h file
4286*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004287void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4288 const char *szLabel,
4289 uint32_t uConvertTypes,
4290 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004291{
4292 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004293 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4294 szLabel,
4295 uConvertTypes,
4296 pnValue,
4297 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004298
4299 if(pMe->uLastError == QCBOR_SUCCESS) {
4300 // The above conversion succeeded
4301 return;
4302 }
4303
4304 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4305 // The above conversion failed in a way that code below can't correct
4306 return;
4307 }
4308
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004309 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004310}
4311
4312
Laurence Lundblade93d89472020-10-03 22:30:50 -07004313static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004314{
4315 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004316 case QCBOR_TYPE_DOUBLE:
4317 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004318#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004319 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004320 // Can't use llround here because it will not convert values
4321 // greater than INT64_MAX and less than UINT64_MAX that
4322 // need to be converted so it is more complicated.
4323 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4324 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4325 if(isnan(pItem->val.dfnum)) {
4326 return QCBOR_ERR_FLOAT_EXCEPTION;
4327 } else if(pItem->val.dfnum < 0) {
4328 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4329 } else {
4330 double dRounded = round(pItem->val.dfnum);
4331 // See discussion in DecodeDateEpoch() for
4332 // explanation of - 0x7ff
4333 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4334 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4335 }
4336 *puValue = (uint64_t)dRounded;
4337 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004338 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004339 if(isnan(pItem->val.fnum)) {
4340 return QCBOR_ERR_FLOAT_EXCEPTION;
4341 } else if(pItem->val.fnum < 0) {
4342 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4343 } else {
4344 float fRounded = roundf(pItem->val.fnum);
4345 // See discussion in DecodeDateEpoch() for
4346 // explanation of - 0x7ff
4347 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4348 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4349 }
4350 *puValue = (uint64_t)fRounded;
4351 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004352 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004353 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4354 // round() and roundf() shouldn't result in exceptions here, but
4355 // catch them to be robust and thorough. Don't try to
4356 // distinguish between the various exceptions because it seems
4357 // they vary by CPU, compiler and OS.
4358 return QCBOR_ERR_FLOAT_EXCEPTION;
4359 }
4360
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004361 } else {
4362 return QCBOR_ERR_UNEXPECTED_TYPE;
4363 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004364#else
4365 return QCBOR_ERR_HW_FLOAT_DISABLED;
4366#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004367 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004368
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004369 case QCBOR_TYPE_INT64:
4370 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4371 if(pItem->val.int64 >= 0) {
4372 *puValue = (uint64_t)pItem->val.int64;
4373 } else {
4374 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4375 }
4376 } else {
4377 return QCBOR_ERR_UNEXPECTED_TYPE;
4378 }
4379 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004380
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004381 case QCBOR_TYPE_UINT64:
4382 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4383 *puValue = pItem->val.uint64;
4384 } else {
4385 return QCBOR_ERR_UNEXPECTED_TYPE;
4386 }
4387 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004388
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004389 default:
4390 return QCBOR_ERR_UNEXPECTED_TYPE;
4391 }
4392
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004393 return QCBOR_SUCCESS;
4394}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004395
4396
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004397void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004398 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004399 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004400 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004401{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004402 if(pMe->uLastError != QCBOR_SUCCESS) {
4403 return;
4404 }
4405
Laurence Lundbladec4537442020-04-14 18:53:22 -07004406 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004407
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004408 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4409 if(uError) {
4410 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004411 return;
4412 }
4413
Laurence Lundbladea826c502020-05-10 21:07:00 -07004414 if(pItem) {
4415 *pItem = Item;
4416 }
4417
Laurence Lundblade93d89472020-10-03 22:30:50 -07004418 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004419}
4420
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004421
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004422void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004423 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004424 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004425 uint64_t *puValue,
4426 QCBORItem *pItem)
4427{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004428 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004429 if(pMe->uLastError != QCBOR_SUCCESS) {
4430 return;
4431 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004432
Laurence Lundblade93d89472020-10-03 22:30:50 -07004433 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004434}
4435
4436
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004437void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004438 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004439 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004440 uint64_t *puValue,
4441 QCBORItem *pItem)
4442{
4443 if(pMe->uLastError != QCBOR_SUCCESS) {
4444 return;
4445 }
4446
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004447 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004448 if(pMe->uLastError != QCBOR_SUCCESS) {
4449 return;
4450 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004451
Laurence Lundblade93d89472020-10-03 22:30:50 -07004452 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004453}
4454
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004455
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004456
Laurence Lundblade93d89472020-10-03 22:30:50 -07004457static QCBORError
4458UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004459{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004460 switch(pItem->uDataType) {
4461
4462 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004463 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004464 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4465 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004466 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004467 }
4468 break;
4469
4470 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004471 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004472 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4473 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004474 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004475 }
4476 break;
4477
4478#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4479
4480 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004481 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004482 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004483 pItem->val.expAndMantissa.nExponent,
4484 puValue,
4485 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004486 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004487 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004488 }
4489 break;
4490
4491 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004492 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004493 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4494 pItem->val.expAndMantissa.nExponent,
4495 puValue,
4496 Exponentitate2);
4497 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004498 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004499 }
4500 break;
4501
4502 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004503 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004504 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004505 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004506 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004507 if(uErr != QCBOR_SUCCESS) {
4508 return uErr;
4509 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004510 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004511 pItem->val.expAndMantissa.nExponent,
4512 puValue,
4513 Exponentitate10);
4514 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004515 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004516 }
4517 break;
4518
4519 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004520 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004521 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4522 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004523 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004524 }
4525 break;
4526
4527 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004528 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004529 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004530 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004531 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004532 if(uErr != QCBOR_SUCCESS) {
4533 return uErr;
4534 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004535 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004536 pItem->val.expAndMantissa.nExponent,
4537 puValue,
4538 Exponentitate2);
4539 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004540 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004541 }
4542 break;
4543
4544 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004545 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004546 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4547 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004548 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004549 }
4550 break;
Laurence Lundblade1ddc1f22020-12-06 05:29:05 -08004551#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004552 default:
4553 return QCBOR_ERR_UNEXPECTED_TYPE;
4554 }
4555}
4556
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004557
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004558/*
4559 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004560 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004561void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004562{
4563 QCBORItem Item;
4564
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004565 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004566
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004567 if(pMe->uLastError == QCBOR_SUCCESS) {
4568 // The above conversion succeeded
4569 return;
4570 }
4571
4572 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4573 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004574 return;
4575 }
4576
Laurence Lundblade93d89472020-10-03 22:30:50 -07004577 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004578}
4579
Laurence Lundbladec4537442020-04-14 18:53:22 -07004580
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004581/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004582 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004583*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004584void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004585 int64_t nLabel,
4586 uint32_t uConvertTypes,
4587 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004588{
4589 QCBORItem Item;
4590
Laurence Lundblade93d89472020-10-03 22:30:50 -07004591 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4592 nLabel,
4593 uConvertTypes,
4594 puValue,
4595 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004596
4597 if(pMe->uLastError == QCBOR_SUCCESS) {
4598 // The above conversion succeeded
4599 return;
4600 }
4601
4602 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4603 // The above conversion failed in a way that code below can't correct
4604 return;
4605 }
4606
Laurence Lundblade93d89472020-10-03 22:30:50 -07004607 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004608}
4609
4610
4611/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004612 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004613*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004614void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004615 const char *szLabel,
4616 uint32_t uConvertTypes,
4617 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004618{
4619 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004620 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4621 szLabel,
4622 uConvertTypes,
4623 puValue,
4624 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004625
4626 if(pMe->uLastError == QCBOR_SUCCESS) {
4627 // The above conversion succeeded
4628 return;
4629 }
4630
4631 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4632 // The above conversion failed in a way that code below can't correct
4633 return;
4634 }
4635
Laurence Lundblade93d89472020-10-03 22:30:50 -07004636 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004637}
4638
4639
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004640
4641
Laurence Lundblade9b334962020-08-27 10:55:53 -07004642static QCBORError ConvertDouble(const QCBORItem *pItem,
4643 uint32_t uConvertTypes,
4644 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004645{
4646 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004647 case QCBOR_TYPE_FLOAT:
4648#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4649 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4650 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004651 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004652 *pdValue = (double)pItem->val.fnum;
4653 } else {
4654 return QCBOR_ERR_UNEXPECTED_TYPE;
4655 }
4656 }
Laurence Lundblade1ddc1f22020-12-06 05:29:05 -08004657#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004658 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade1ddc1f22020-12-06 05:29:05 -08004659#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004660 break;
4661
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004662 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004663 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4664 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004665 *pdValue = pItem->val.dfnum;
4666 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004667 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004668 }
4669 }
4670 break;
4671
4672 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004673#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004674 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004675 // A simple cast seems to do the job with no worry of exceptions.
4676 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004677 *pdValue = (double)pItem->val.int64;
4678
4679 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004680 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004681 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004682#else
4683 return QCBOR_ERR_HW_FLOAT_DISABLED;
4684#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004685 break;
4686
4687 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004688#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004689 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004690 // A simple cast seems to do the job with no worry of exceptions.
4691 // There will be precision loss for some values.
4692 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004693 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004694 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004695 }
4696 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004697#else
4698 return QCBOR_ERR_HW_FLOAT_DISABLED;
4699#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004700
4701 default:
4702 return QCBOR_ERR_UNEXPECTED_TYPE;
4703 }
4704
4705 return QCBOR_SUCCESS;
4706}
4707
4708
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004709void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004710 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004711 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004712 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004713{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004714 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004715 return;
4716 }
4717
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004718 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004719
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004720 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004721 if(uError) {
4722 pMe->uLastError = (uint8_t)uError;
4723 return;
4724 }
4725
4726 if(pItem) {
4727 *pItem = Item;
4728 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004729
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004730 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004731}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004732
Laurence Lundbladec4537442020-04-14 18:53:22 -07004733
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004734void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4735 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004736 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004737 double *pdValue,
4738 QCBORItem *pItem)
4739{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004740 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004741 if(pMe->uLastError != QCBOR_SUCCESS) {
4742 return;
4743 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004744
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004745 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004746}
4747
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004748
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004749void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4750 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004751 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004752 double *pdValue,
4753 QCBORItem *pItem)
4754{
4755 if(pMe->uLastError != QCBOR_SUCCESS) {
4756 return;
4757 }
4758
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004759 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004760 if(pMe->uLastError != QCBOR_SUCCESS) {
4761 return;
4762 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004763
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004764 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004765}
4766
4767
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004768#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004769static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4770{
4771 double dResult;
4772
4773 dResult = 0.0;
4774 const uint8_t *pByte = BigNum.ptr;
4775 size_t uLen = BigNum.len;
4776 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004777 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004778 while(uLen--) {
4779 dResult = (dResult * 256.0) + (double)*pByte++;
4780 }
4781
4782 return dResult;
4783}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004784#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4785
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004786
Laurence Lundblade93d89472020-10-03 22:30:50 -07004787static QCBORError
4788DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004789{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004790#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004791 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004792 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4793
4794 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004795 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004796
4797#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004798 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004799 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004800 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004801 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4802 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4803 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004804 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004805 }
4806 break;
4807
4808 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004809 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004810 // Underflow gives 0, overflow gives infinity
4811 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4812 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004813 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004814 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004815 }
4816 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004817#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004818
4819 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004820 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004821 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4822 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004823 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004824 }
4825 break;
4826
4827 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004828 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004829 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004830 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004831 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004832 }
4833 break;
4834
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004835#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004836 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004837 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004838 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4839 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4840 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004841 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004842 }
4843 break;
4844
4845 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004846 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004847 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4848 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4849 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004850 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004851 }
4852 break;
4853
4854 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004855 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004856 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4857 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4858 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004859 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004860 }
4861 break;
4862
4863 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004864 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004865 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004866 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4867 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004868 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004869 }
4870 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004871#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4872
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004873 default:
4874 return QCBOR_ERR_UNEXPECTED_TYPE;
4875 }
4876
4877 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004878
4879#else
4880 (void)pItem;
4881 (void)uConvertTypes;
4882 (void)pdValue;
4883 return QCBOR_ERR_HW_FLOAT_DISABLED;
4884#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4885
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004886}
4887
4888
4889/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004890 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004891*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004892void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4893 uint32_t uConvertTypes,
4894 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004895{
4896
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004897 QCBORItem Item;
4898
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004899 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004900
4901 if(pMe->uLastError == QCBOR_SUCCESS) {
4902 // The above conversion succeeded
4903 return;
4904 }
4905
4906 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4907 // The above conversion failed in a way that code below can't correct
4908 return;
4909 }
4910
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004911 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004912}
4913
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004914
4915/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004916 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004917*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004918void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4919 int64_t nLabel,
4920 uint32_t uConvertTypes,
4921 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004922{
4923 QCBORItem Item;
4924
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004925 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004926
4927 if(pMe->uLastError == QCBOR_SUCCESS) {
4928 // The above conversion succeeded
4929 return;
4930 }
4931
4932 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4933 // The above conversion failed in a way that code below can't correct
4934 return;
4935 }
4936
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004937 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004938}
4939
4940
4941/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004942 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004943*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004944void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4945 const char *szLabel,
4946 uint32_t uConvertTypes,
4947 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004948{
4949 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004950 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004951
4952 if(pMe->uLastError == QCBOR_SUCCESS) {
4953 // The above conversion succeeded
4954 return;
4955 }
4956
4957 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4958 // The above conversion failed in a way that code below can't correct
4959 return;
4960 }
4961
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004962 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004963}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004964
4965
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004966
4967
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004968#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004969static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4970{
4971 while((uInt & 0xff00000000000000UL) == 0) {
4972 uInt = uInt << 8;
4973 };
4974
4975 UsefulOutBuf UOB;
4976
4977 UsefulOutBuf_Init(&UOB, Buffer);
4978
4979 while(uInt) {
4980 const uint64_t xx = uInt & 0xff00000000000000UL;
4981 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4982 uInt = uInt << 8;
4983 (void)xx;
4984 }
4985
4986 return UsefulOutBuf_OutUBuf(&UOB);
4987}
4988
4989
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004990static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4991 TagSpecification TagSpec,
4992 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004993{
4994 QCBORError uErr;
4995 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004996 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004997 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004998 if(uErr != QCBOR_SUCCESS) {
4999 goto Done;
5000 }
5001
5002 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5003 break; // Successful exit. Moving on to finish decoding.
5004 }
5005
5006 // The item is an array, which means an undecoded
5007 // mantissa and exponent, so decode it. It will then
5008 // have a different type and exit the loop if.
5009 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5010 if(uErr != QCBOR_SUCCESS) {
5011 goto Done;
5012 }
5013
5014 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005015 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005016 }
5017Done:
5018 return uErr;
5019}
5020
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005021
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005022static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005023 TagSpecification TagSpec,
5024 QCBORItem *pItem,
5025 int64_t *pnMantissa,
5026 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005027{
5028 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005029
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005030 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005031 if(uErr != QCBOR_SUCCESS) {
5032 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005033 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005034
Laurence Lundblade9b334962020-08-27 10:55:53 -07005035 switch (pItem->uDataType) {
5036
5037 case QCBOR_TYPE_DECIMAL_FRACTION:
5038 case QCBOR_TYPE_BIGFLOAT:
5039 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5040 *pnExponent = pItem->val.expAndMantissa.nExponent;
5041 break;
5042
5043 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5044 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5045 *pnExponent = pItem->val.expAndMantissa.nExponent;
5046 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5047 break;
5048
5049 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5050 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5051 *pnExponent = pItem->val.expAndMantissa.nExponent;
5052 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5053 break;
5054
5055 default:
5056 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5057 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005058
5059 Done:
5060 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005061}
5062
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005063
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005064static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005065 TagSpecification TagSpec,
5066 QCBORItem *pItem,
5067 UsefulBuf BufferForMantissa,
5068 UsefulBufC *pMantissa,
5069 bool *pbIsNegative,
5070 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005071{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005072 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005073
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005074 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005075 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005076 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005077 }
5078
5079 uint64_t uMantissa;
5080
5081 switch (pItem->uDataType) {
5082
5083 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005084 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005085 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5086 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5087 *pbIsNegative = false;
5088 } else {
5089 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5090 *pbIsNegative = true;
5091 }
5092 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5093 *pnExponent = pItem->val.expAndMantissa.nExponent;
5094 break;
5095
5096 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005097 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005098 *pnExponent = pItem->val.expAndMantissa.nExponent;
5099 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5100 *pbIsNegative = false;
5101 break;
5102
5103 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005104 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005105 *pnExponent = pItem->val.expAndMantissa.nExponent;
5106 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5107 *pbIsNegative = true;
5108 break;
5109
5110 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005111 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005112 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005113
5114Done:
5115 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005116}
5117
5118
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005119/*
5120 Public function, see header qcbor/qcbor_decode.h file
5121*/
5122void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5123 uint8_t uTagRequirement,
5124 int64_t *pnMantissa,
5125 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005126{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005127 if(pMe->uLastError != QCBOR_SUCCESS) {
5128 return;
5129 }
5130
5131 QCBORItem Item;
5132 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5133 if(uError) {
5134 pMe->uLastError = (uint8_t)uError;
5135 return;
5136 }
5137
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005138 const TagSpecification TagSpec =
5139 {
5140 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005141 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5142 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5143 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005144 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005145
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005146 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005147}
5148
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005149
5150/*
5151 Public function, see header qcbor/qcbor_decode.h file
5152*/
5153void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005154 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005155 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005156 int64_t *pnMantissa,
5157 int64_t *pnExponent)
5158{
5159 if(pMe->uLastError != QCBOR_SUCCESS) {
5160 return;
5161 }
5162
5163 QCBORItem Item;
5164 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5165
5166 const TagSpecification TagSpec =
5167 {
5168 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005169 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5170 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5171 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005172 };
5173
5174 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5175}
5176
5177
5178/*
5179 Public function, see header qcbor/qcbor_decode.h file
5180*/
5181void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005182 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005183 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005184 int64_t *pnMantissa,
5185 int64_t *pnExponent)
5186{
5187 if(pMe->uLastError != QCBOR_SUCCESS) {
5188 return;
5189 }
5190
5191 QCBORItem Item;
5192 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5193
5194 const TagSpecification TagSpec =
5195 {
5196 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005197 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5198 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5199 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005200 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005201
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005202 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5203}
5204
5205
5206/*
5207 Public function, see header qcbor/qcbor_decode.h file
5208*/
5209void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5210 uint8_t uTagRequirement,
5211 UsefulBuf MantissaBuffer,
5212 UsefulBufC *pMantissa,
5213 bool *pbMantissaIsNegative,
5214 int64_t *pnExponent)
5215{
5216 if(pMe->uLastError != QCBOR_SUCCESS) {
5217 return;
5218 }
5219
5220 QCBORItem Item;
5221 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5222 if(uError) {
5223 pMe->uLastError = (uint8_t)uError;
5224 return;
5225 }
5226
5227 const TagSpecification TagSpec =
5228 {
5229 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005230 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5231 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5232 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005233 };
5234
Laurence Lundblade93d89472020-10-03 22:30:50 -07005235 ProcessMantissaAndExponentBig(pMe,
5236 TagSpec,
5237 &Item,
5238 MantissaBuffer,
5239 pMantissa,
5240 pbMantissaIsNegative,
5241 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005242}
5243
5244
5245/*
5246 Public function, see header qcbor/qcbor_decode.h file
5247*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005248void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005249 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005250 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005251 UsefulBuf BufferForMantissa,
5252 UsefulBufC *pMantissa,
5253 bool *pbIsNegative,
5254 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005255{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005256 if(pMe->uLastError != QCBOR_SUCCESS) {
5257 return;
5258 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005259
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005260 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005261 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005262 if(pMe->uLastError != QCBOR_SUCCESS) {
5263 return;
5264 }
5265
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005266 const TagSpecification TagSpec =
5267 {
5268 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005269 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5270 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5271 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005272 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005273
Laurence Lundblade93d89472020-10-03 22:30:50 -07005274 ProcessMantissaAndExponentBig(pMe,
5275 TagSpec,
5276 &Item,
5277 BufferForMantissa,
5278 pMantissa,
5279 pbIsNegative,
5280 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005281}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005282
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005283
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005284/*
5285 Public function, see header qcbor/qcbor_decode.h file
5286*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005287void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005288 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005289 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005290 UsefulBuf BufferForMantissa,
5291 UsefulBufC *pMantissa,
5292 bool *pbIsNegative,
5293 int64_t *pnExponent)
5294{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005295 if(pMe->uLastError != QCBOR_SUCCESS) {
5296 return;
5297 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005298
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005299 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005300 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5301 if(pMe->uLastError != QCBOR_SUCCESS) {
5302 return;
5303 }
5304
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005305 const TagSpecification TagSpec =
5306 {
5307 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005308 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5309 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5310 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005311 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005312
5313 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5314}
5315
5316
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005317/*
5318 Public function, see header qcbor/qcbor_decode.h file
5319*/
5320void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5321 uint8_t uTagRequirement,
5322 int64_t *pnMantissa,
5323 int64_t *pnExponent)
5324{
5325 if(pMe->uLastError != QCBOR_SUCCESS) {
5326 return;
5327 }
5328
5329 QCBORItem Item;
5330 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5331 if(uError) {
5332 pMe->uLastError = (uint8_t)uError;
5333 return;
5334 }
5335 const TagSpecification TagSpec =
5336 {
5337 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005338 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5339 QCBOR_TYPE_BIGFLOAT_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_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005351 int64_t nLabel,
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_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5362 if(pMe->uLastError != QCBOR_SUCCESS) {
5363 return;
5364 }
5365
5366 const TagSpecification TagSpec =
5367 {
5368 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005369 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5370 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5371 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005372 };
5373
5374 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5375}
5376
5377
5378/*
5379 Public function, see header qcbor/qcbor_decode.h file
5380*/
5381void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005382 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005383 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005384 int64_t *pnMantissa,
5385 int64_t *pnExponent)
5386{
5387 if(pMe->uLastError != QCBOR_SUCCESS) {
5388 return;
5389 }
5390
5391 QCBORItem Item;
5392 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5393 if(pMe->uLastError != QCBOR_SUCCESS) {
5394 return;
5395 }
5396
5397 const TagSpecification TagSpec =
5398 {
5399 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005400 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5401 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5402 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005403 };
5404
5405 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5406}
5407
5408
5409/*
5410 Public function, see header qcbor/qcbor_decode.h file
5411*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005412void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5413 uint8_t uTagRequirement,
5414 UsefulBuf MantissaBuffer,
5415 UsefulBufC *pMantissa,
5416 bool *pbMantissaIsNegative,
5417 int64_t *pnExponent)
5418{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005419 if(pMe->uLastError != QCBOR_SUCCESS) {
5420 return;
5421 }
5422
5423 QCBORItem Item;
5424 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5425 if(uError) {
5426 pMe->uLastError = (uint8_t)uError;
5427 return;
5428 }
5429
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005430 const TagSpecification TagSpec =
5431 {
5432 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005433 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5434 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5435 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005436 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005437
5438 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005439}
5440
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005441
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005442/*
5443 Public function, see header qcbor/qcbor_decode.h file
5444*/
5445void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005446 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005447 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005448 UsefulBuf BufferForMantissa,
5449 UsefulBufC *pMantissa,
5450 bool *pbIsNegative,
5451 int64_t *pnExponent)
5452{
5453 if(pMe->uLastError != QCBOR_SUCCESS) {
5454 return;
5455 }
5456
5457 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005458 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5459 if(pMe->uLastError != QCBOR_SUCCESS) {
5460 return;
5461 }
5462
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005463 const TagSpecification TagSpec =
5464 {
5465 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005466 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5467 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5468 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005469 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005470
Laurence Lundblade93d89472020-10-03 22:30:50 -07005471 ProcessMantissaAndExponentBig(pMe,
5472 TagSpec,
5473 &Item,
5474 BufferForMantissa,
5475 pMantissa,
5476 pbIsNegative,
5477 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005478}
5479
5480
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005481/*
5482 Public function, see header qcbor/qcbor_decode.h file
5483*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005484void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005485 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005486 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005487 UsefulBuf BufferForMantissa,
5488 UsefulBufC *pMantissa,
5489 bool *pbIsNegative,
5490 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005491{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005492 if(pMe->uLastError != QCBOR_SUCCESS) {
5493 return;
5494 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005495
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005496 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005497 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5498 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005499 return;
5500 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005501
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005502 const TagSpecification TagSpec =
5503 {
5504 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005505 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5506 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5507 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005508 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005509
Laurence Lundblade93d89472020-10-03 22:30:50 -07005510 ProcessMantissaAndExponentBig(pMe,
5511 TagSpec,
5512 &Item,
5513 BufferForMantissa,
5514 pMantissa,
5515 pbIsNegative,
5516 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005517}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005518
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005519#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */