blob: afc36514ef4678b0ac3c539c27618ae404676709 [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 Lundbladec7114722020-08-13 05:11:40 -070042#endif
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{
79 if(!QCBORItem_IsMapOrArray(pMe)){
80 return false;
81 }
82
83 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
84 return false;
85 }
86 return true;
87}
88
89
Laurence Lundbladeee851742020-01-08 08:37:05 -080090/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070091 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080092 ===========================================================================*/
93
Laurence Lundblade9c905e82020-04-25 11:31:38 -070094/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070095 See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
Laurence Lundblade93d89472020-10-03 22:30:50 -070096 the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -070097 */
98
Laurence Lundblade24d509a2020-06-06 18:43:15 -070099
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700100static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700101DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700102{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700103 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700104 /*
105 Limit in DecodeNesting_Descend against more than
106 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
107 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700108 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700109}
110
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700111
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700112static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700113DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700114{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700115 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700116 /*
117 Limit in DecodeNesting_Descend against more than
118 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
119 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700120 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700121}
122
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700123
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700124static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700125DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700126{
127 return pNesting->pCurrentBounded->u.ma.uStartOffset;
128}
129
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700130
Laurence Lundblade085d7952020-07-24 10:26:30 -0700131static inline bool
132DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
133{
134 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
135 return true;
136 } else {
137 return false;
138 }
139}
140
141
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700142static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700143DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700144{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700145 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700146 return true;
147 } else {
148 return false;
149 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700150}
151
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700152
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700153static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700154DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700155{
156 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700157 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700158 return false;
159 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700160 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700161 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700162 return false;
163 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700164 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700165 return true;
166}
167
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700168
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700169static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700170DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700171{
172 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700173 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700174 return true;
175 }
176 return false;
177}
178
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700179
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700180static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700181{
182 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
183 return true;
184 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700185 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700186 return true;
187 }
188 return false;
189}
190
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700191
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700192static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700193{
194 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700195 /*
196 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
197 larger than DecodeNesting_EnterBoundedMode which keeps it less than
198 uin32_t so the cast is safe.
199 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700200 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700201
202 if(bIsEmpty) {
203 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
204 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700205}
206
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700207
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700208static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700209{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700210 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700211}
212
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700213
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700214static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700215DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700216{
217 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700218 // No bounded map or array set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700219 return false;
220 }
221 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700222 // Not a map or array; end of those is by byte count
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700223 return false;
224 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700225 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
226 // In a traveral at a level deeper than the bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700227 return false;
228 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700229 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700230 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700231 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700232 return false;
233 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700234 // All checks passed, got to the end of an array or map
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700235 return true;
236}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700237
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700238
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700239static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700240DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700241{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700242 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700243 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
244 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700245 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700246 return false;
247 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700248}
249
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700250
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700251static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700252DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700253{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700254 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
255 return true;
256 } else {
257 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700258 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700259}
260
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700261
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700262static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700263DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700264{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700265 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700266 return false;
267 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700268
269 if(pNesting->pCurrentBounded->uLevelType != uType) {
270 return false;
271 }
272
273 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700274}
275
Laurence Lundblade02625d42020-06-25 14:41:41 -0700276
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700277static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700278DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700279{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700280 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700281 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700282}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700283
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700284
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700285static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700286DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
287{
288 // Only call on a defnite length array / map
289 pNesting->pCurrent->u.ma.uCountCursor++;
290}
291
292
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700293static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700294DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
295{
296 pNesting->pCurrent--;
297}
298
Laurence Lundblade02625d42020-06-25 14:41:41 -0700299
300static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700301DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700302{
303 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700304 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700305 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700306 }
307
308 // The actual descend
309 pNesting->pCurrent++;
310
311 pNesting->pCurrent->uLevelType = uType;
312
313 return QCBOR_SUCCESS;
314}
315
316
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700317static inline QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700318DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700319{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700320 /*
321 Should only be called on map/array.
322
323 Have descended into this before this is called. The job here is
324 just to mark it in bounded mode.
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700325
326 Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
327 uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700328 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700329 if(uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700330 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700331 }
332
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700333 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700334
335 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700336
337 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700338}
339
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700340
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700341static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700342DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700343 uint8_t uQCBORType,
344 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700345{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700346 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700347
348 if(uCount == 0) {
349 // Nothing to do for empty definite lenth arrays. They are just are
350 // effectively the same as an item that is not a map or array
351 goto Done;
352 // Empty indefinite length maps and arrays are handled elsewhere
353 }
354
355 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700356 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
357 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700358 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700359 goto Done;
360 }
361
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700362 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700363 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700364 goto Done;
365 }
366
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700367 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700368 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
369 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700370
371 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700372
373Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700374 return uError;;
375}
376
377
378static inline void
379DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
380{
381 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
382}
383
384
385static inline void
386DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
387{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700388 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700389 pNesting->pCurrentBounded--;
390 if(DecodeNesting_IsCurrentBounded(pNesting)) {
391 break;
392 }
393 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700394}
395
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700396static inline void
397DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
398{
399 pNesting->pCurrent = pNesting->pCurrentBounded;
400}
401
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700402
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700403static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700404DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700405 uint32_t uEndOffset,
406 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700407{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700408 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700409
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700410 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700411 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700412 goto Done;
413 }
414
Laurence Lundblade02625d42020-06-25 14:41:41 -0700415 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700416 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
417 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700418
Laurence Lundblade02625d42020-06-25 14:41:41 -0700419 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700420 pNesting->pCurrentBounded = pNesting->pCurrent;
421
422Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700423 return uError;;
424}
425
Laurence Lundbladed0304932020-06-27 10:59:38 -0700426
427static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700428DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700429{
430 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700431}
432
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700433
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700434static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700435DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700436{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700437 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700438 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
439 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700440}
441
442
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700443static inline void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700444DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700445{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700446 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700447 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700448 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700449}
450
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700451
Laurence Lundblade02625d42020-06-25 14:41:41 -0700452static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700453DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700454{
455 *pNesting = *pSave;
456}
457
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700458
Laurence Lundblade02625d42020-06-25 14:41:41 -0700459static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700460DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700461{
462 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
463}
464
465
Laurence Lundblade02625d42020-06-25 14:41:41 -0700466static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700467DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700468{
469 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
470}
471
472
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700473
Laurence Lundbladeee851742020-01-08 08:37:05 -0800474/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800475 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
476
477 The following four functions are pretty wrappers for invocation of
478 the string allocator supplied by the caller.
479
Laurence Lundbladeee851742020-01-08 08:37:05 -0800480 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800481
Laurence Lundbladeee851742020-01-08 08:37:05 -0800482static inline void
483StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800484{
485 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
486}
487
Laurence Lundbladeee851742020-01-08 08:37:05 -0800488// StringAllocator_Reallocate called with pMem NULL is
489// equal to StringAllocator_Allocate()
490static inline UsefulBuf
491StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
492 void *pMem,
493 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800494{
495 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
496}
497
Laurence Lundbladeee851742020-01-08 08:37:05 -0800498static inline UsefulBuf
499StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800500{
501 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
502}
503
Laurence Lundbladeee851742020-01-08 08:37:05 -0800504static inline void
505StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800506{
507 if(pMe->pfAllocator) {
508 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
509 }
510}
511
512
513
Laurence Lundbladeee851742020-01-08 08:37:05 -0800514/*===========================================================================
515 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700516
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800517 See qcbor/qcbor_decode.h for definition of the object
518 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800519 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700520/*
521 Public function, see header file
522 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800523void QCBORDecode_Init(QCBORDecodeContext *me,
524 UsefulBufC EncodedCBOR,
525 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700526{
527 memset(me, 0, sizeof(QCBORDecodeContext));
528 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800529 // Don't bother with error check on decode mode. If a bad value is
530 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700531 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700532 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700533 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700534 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700535 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700536}
537
538
539/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700540 Public function, see header file
541 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800542void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
543 QCBORStringAllocate pfAllocateFunction,
544 void *pAllocateContext,
545 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700546{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800547 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
548 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
549 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700550}
551
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800552
553/*
554 Public function, see header file
555 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700556void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800557 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700558{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700559 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700560 (void)pMe;
561 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700562}
563
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700564
565/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800566 This decodes the fundamental part of a CBOR data item, the type and
567 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800568
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700569 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800570
Laurence Lundbladeee851742020-01-08 08:37:05 -0800571 This does the network->host byte order conversion. The conversion
572 here also results in the conversion for floats in addition to that
573 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800574
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700575 This returns:
576 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800577
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800578 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800579 tags and floats and length for strings and arrays
580
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800581 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800582 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800583
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800584 The int type is preferred to uint8_t for some variables as this
585 avoids integer promotions, can reduce code size and makes
586 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700587
588 @retval QCBOR_ERR_UNSUPPORTED
589
590 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700591 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700592static inline QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800593 int *pnMajorType,
594 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800595 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700596{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700597 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800598
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700599 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800600 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800601
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700602 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800603 const int nTmpMajorType = nInitialByte >> 5;
604 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800605
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800606 // Where the number or argument accumulates
607 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800608
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800609 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700610 // Need to get 1,2,4 or 8 additional argument bytes. Map
611 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800612 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800613
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800614 // Loop getting all the bytes in the argument
615 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800616 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800617 // This shift and add gives the endian conversion
618 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
619 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800620 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800621 // The reserved and thus-far unused additional info values
622 nReturn = QCBOR_ERR_UNSUPPORTED;
623 goto Done;
624 } else {
625 // Less than 24, additional info is argument or 31, an indefinite length
626 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800627 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700628 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800629
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700630 if(UsefulInputBuf_GetError(pUInBuf)) {
631 nReturn = QCBOR_ERR_HIT_END;
632 goto Done;
633 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800634
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700635 // All successful if we got here.
636 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800637 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800638 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800639 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800640
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700641Done:
642 return nReturn;
643}
644
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800645
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800647 CBOR doesn't explicitly specify two's compliment for integers but all
648 CPUs use it these days and the test vectors in the RFC are so. All
649 integers in the CBOR structure are positive and the major type
650 indicates positive or negative. CBOR can express positive integers
651 up to 2^x - 1 where x is the number of bits and negative integers
652 down to 2^x. Note that negative numbers can be one more away from
653 zero than positive. Stdint, as far as I can tell, uses two's
654 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800655
Laurence Lundblade9b334962020-08-27 10:55:53 -0700656 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800657 used carefully here, and in particular why it isn't used in the interface.
658 Also see
659 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
660
661 Int is used for values that need less than 16-bits and would be subject
662 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700663
664 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700665 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700666static inline QCBORError
Laurence Lundbladeee851742020-01-08 08:37:05 -0800667DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700668{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700669 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800670
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700671 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
672 if (uNumber <= INT64_MAX) {
673 pDecodedItem->val.int64 = (int64_t)uNumber;
674 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800675
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700676 } else {
677 pDecodedItem->val.uint64 = uNumber;
678 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800679
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700680 }
681 } else {
682 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800683 // CBOR's representation of negative numbers lines up with the
684 // two-compliment representation. A negative integer has one
685 // more in range than a positive integer. INT64_MIN is
686 // equal to (-INT64_MAX) - 1.
687 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700688 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800689
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700690 } else {
691 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000692 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700693 nReturn = QCBOR_ERR_INT_OVERFLOW;
694 }
695 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800696
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700697 return nReturn;
698}
699
700// Make sure #define value line up as DecodeSimple counts on this.
701#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
702#error QCBOR_TYPE_FALSE macro value wrong
703#endif
704
705#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
706#error QCBOR_TYPE_TRUE macro value wrong
707#endif
708
709#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
710#error QCBOR_TYPE_NULL macro value wrong
711#endif
712
713#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
714#error QCBOR_TYPE_UNDEF macro value wrong
715#endif
716
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700717#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
718#error QCBOR_TYPE_BREAK macro value wrong
719#endif
720
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700721#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
722#error QCBOR_TYPE_DOUBLE macro value wrong
723#endif
724
725#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
726#error QCBOR_TYPE_FLOAT macro value wrong
727#endif
728
729/*
730 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700731
732 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
733
734 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700735 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700736static inline QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800737DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700738{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700739 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800740
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700741 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800742 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundblade93d89472020-10-03 22:30:50 -0700743 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast
744 // is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800745 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800746
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800747 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800748 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
749 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800750
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700751 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700752#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700753 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700754 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700755 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700756 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
757 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700758#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700759 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700760#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700761 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700762 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700763 // Single precision is normally returned as a double
764 // since double is widely supported, there is no loss of
765 // precision, it makes it easy for the caller in
766 // most cases and it can be converted back to single
767 // with no loss of precision
768 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700769 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700770 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700771 {
772 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
773#ifndef QCBOR_DISABLE_FLOAT_HW_USE
774 // In the normal case, use HW to convert float to double.
775 pDecodedItem->val.dfnum = (double)f;
776 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700777#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700778 // Use of float HW is disabled, return as a float.
779 pDecodedItem->val.fnum = f;
780 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
781
782 // IEEE754_FloatToDouble() could be used here to return
783 // as a double, but it adds object code and most likely
784 // anyone disabling FLOAT HW use doesn't care about
785 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700786#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700787 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700788 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700789
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700790 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700791 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700792 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700793 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800794
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700795 case CBOR_SIMPLEV_FALSE: // 20
796 case CBOR_SIMPLEV_TRUE: // 21
797 case CBOR_SIMPLEV_NULL: // 22
798 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700799 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700800 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800801
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700802 case CBOR_SIMPLEV_ONEBYTE: // 24
803 if(uNumber <= CBOR_SIMPLE_BREAK) {
804 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700805 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700806 goto Done;
807 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800808 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700809 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800810
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700811 default: // 0-19
812 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800813 /*
814 DecodeTypeAndNumber will make uNumber equal to
815 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
816 safe because the 2, 4 and 8 byte lengths of uNumber are in
817 the double/float cases above
818 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700819 pDecodedItem->val.uSimple = (uint8_t)uNumber;
820 break;
821 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800822
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700823Done:
824 return nReturn;
825}
826
827
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700828/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530829 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700830
831 @retval QCBOR_ERR_HIT_END
832
833 @retval QCBOR_ERR_STRING_ALLOCATE
834
835 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700836 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700837static inline QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800838 int nMajorType,
839 uint64_t uStrLen,
840 UsefulInputBuf *pUInBuf,
841 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700842{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700843 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800844
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800845 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
846 // This check makes the casts to size_t below safe.
847
848 // 4 bytes less than the largest sizeof() so this can be tested by
849 // putting a SIZE_MAX length in the CBOR test input (no one will
850 // care the limit on strings is 4 bytes shorter).
851 if(uStrLen > SIZE_MAX-4) {
852 nReturn = QCBOR_ERR_STRING_TOO_LONG;
853 goto Done;
854 }
855
856 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530857 if(UsefulBuf_IsNULLC(Bytes)) {
858 // Failed to get the bytes for this string item
859 nReturn = QCBOR_ERR_HIT_END;
860 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700861 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530862
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800863 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530864 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800865 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530866 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700867 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530868 goto Done;
869 }
870 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800871 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530872 } else {
873 // Normal case with no string allocator
874 pDecodedItem->val.string = Bytes;
875 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800876 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800877 // Cast because ternary operator causes promotion to integer
878 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
879 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800880
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530881Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700882 return nReturn;
883}
884
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700885
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800886
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700887
888
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700889
890
Laurence Lundbladeee851742020-01-08 08:37:05 -0800891// Make sure the constants align as this is assumed by
892// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700893#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
894#error QCBOR_TYPE_ARRAY value not lined up with major type
895#endif
896#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
897#error QCBOR_TYPE_MAP value not lined up with major type
898#endif
899
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700900/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800901 This gets a single data item and decodes it including preceding
902 optional tagging. This does not deal with arrays and maps and nesting
903 except to decode the data item introducing them. Arrays and maps are
904 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800905
Laurence Lundbladeee851742020-01-08 08:37:05 -0800906 Errors detected here include: an array that is too long to decode,
907 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700908
909 @retval QCBOR_ERR_UNSUPPORTED
910
911 @retval QCBOR_ERR_HIT_END
912
913 @retval QCBOR_ERR_INT_OVERFLOW
914
915 @retval QCBOR_ERR_STRING_ALLOCATE
916
917 @retval QCBOR_ERR_STRING_TOO_LONG
918
919 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
920
921 @retval QCBOR_ERR_BAD_TYPE_7
922
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700923 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800924static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
925 QCBORItem *pDecodedItem,
926 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700927{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700928 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800929
Laurence Lundbladeee851742020-01-08 08:37:05 -0800930 /*
931 Get the major type and the number. Number could be length of more
932 bytes or the value depending on the major type nAdditionalInfo is
933 an encoding of the length of the uNumber and is needed to decode
934 floats and doubles
935 */
Rob Gilton47cc9562020-08-10 12:03:38 +0100936 int nMajorType = 0;
937 uint64_t uNumber = 0;
938 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800939
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700940 memset(pDecodedItem, 0, sizeof(QCBORItem));
941
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800942 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800943
Laurence Lundbladeee851742020-01-08 08:37:05 -0800944 // Error out here if we got into trouble on the type and number. The
945 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700946 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700947 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700948 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800949
Laurence Lundbladeee851742020-01-08 08:37:05 -0800950 // At this point the major type and the value are valid. We've got
951 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800952 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700953 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
954 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800955 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700956 nReturn = QCBOR_ERR_BAD_INT;
957 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800958 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700959 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700960 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800961
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700962 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
963 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800964 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
965 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
966 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
967 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530968 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700969 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800970 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700971 }
972 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800973
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700974 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
975 case CBOR_MAJOR_TYPE_MAP: // Major type 5
976 // Record the number of items in the array or map
977 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700978 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700979 goto Done;
980 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800981 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700982 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700983 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800984 // type conversion OK because of check above
985 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700986 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800987 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800988 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
989 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800991
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700992 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800993 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700994 nReturn = QCBOR_ERR_BAD_INT;
995 } else {
996 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -0700997 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700998 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700999 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001000
Laurence Lundbladeee851742020-01-08 08:37:05 -08001001 case CBOR_MAJOR_TYPE_SIMPLE:
1002 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001003 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001004 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001005
Laurence Lundbladeee851742020-01-08 08:37:05 -08001006 default:
1007 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001008 nReturn = QCBOR_ERR_UNSUPPORTED;
1009 break;
1010 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001011
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001012Done:
1013 return nReturn;
1014}
1015
1016
1017
1018/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001019 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001020 individual chunk items together into one QCBORItem using the string
1021 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001022
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301023 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade9b334962020-08-27 10:55:53 -07001024
1025 @retval QCBOR_ERR_UNSUPPORTED
1026
1027 @retval QCBOR_ERR_HIT_END
1028
1029 @retval QCBOR_ERR_INT_OVERFLOW
1030
1031 @retval QCBOR_ERR_STRING_ALLOCATE
1032
1033 @retval QCBOR_ERR_STRING_TOO_LONG
1034
1035 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1036
1037 @retval QCBOR_ERR_BAD_TYPE_7
1038
1039 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1040
1041 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001042 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001043static inline QCBORError
1044GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001045{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001046 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001047
1048 // Get pointer to string allocator. First use is to pass it to
1049 // GetNext_Item() when option is set to allocate for *every* string.
1050 // Second use here is to allocate space to coallese indefinite
1051 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001052 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1053 &(me->StringAllocator) :
1054 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001055
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001056 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001057 nReturn = GetNext_Item(&(me->InBuf),
1058 pDecodedItem,
1059 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001060 if(nReturn) {
1061 goto Done;
1062 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001063
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001064 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301065 // code in this function from here down can be eliminated. Run tests, except
1066 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001067
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001068 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001069 const uint8_t uStringType = pDecodedItem->uDataType;
1070 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001071 goto Done; // no need to do any work here on non-string types
1072 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001073
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001074 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301075 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001076 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001077 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001078
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301079 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001080 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001081 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1082 goto Done;
1083 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001084
Laurence Lundblade4b270642020-08-14 12:53:07 -07001085 // Loop getting chunks of the indefinite length string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001086 UsefulBufC FullString = NULLUsefulBufC;
1087
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001088 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001089 // Get item for next chunk
1090 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001091 // NULL string allocator passed here. Do not need to allocate
1092 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001093 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001094 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001095 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001096 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001097
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301098 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001099 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001100 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001101 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301102 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001103 break;
1104 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001105
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001106 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301107 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001108 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001109 if(StringChunkItem.uDataType != uStringType ||
1110 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001111 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001112 break;
1113 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001114
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301115 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001116 // The first time throurgh FullString.ptr is NULL and this is
1117 // equivalent to StringAllocator_Allocate()
1118 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1119 UNCONST_POINTER(FullString.ptr),
1120 FullString.len + StringChunkItem.val.string.len);
1121
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001122 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301123 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001124 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001125 break;
1126 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001127
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001128 // Copy new string chunk at the end of string so far.
1129 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001130 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001131
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001132 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1133 // Getting the item failed, clean up the allocated memory
1134 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001135 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001136
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001137Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001138 return nReturn;
1139}
1140
Laurence Lundblade9b334962020-08-27 10:55:53 -07001141static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001142 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001143 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001144 } else if(uTagVal == CBOR_TAG_INVALID16) {
1145 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001146 } else {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001147 // This won't be negative because of code below in GetNext_TaggedItem()
1148 const unsigned uIndex = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
1149 return me->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001150 }
1151}
1152
Laurence Lundblade9b334962020-08-27 10:55:53 -07001153
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001154/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001155 Gets all optional tag data items preceding a data item that is not an
1156 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001157
1158 @retval QCBOR_ERR_UNSUPPORTED
1159
1160 @retval QCBOR_ERR_HIT_END
1161
1162 @retval QCBOR_ERR_INT_OVERFLOW
1163
1164 @retval QCBOR_ERR_STRING_ALLOCATE
1165
1166 @retval QCBOR_ERR_STRING_TOO_LONG
1167
1168 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1169
1170 @retval QCBOR_ERR_BAD_TYPE_7
1171
1172 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1173
1174 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1175
1176 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001177 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001178static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001179GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001180{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001181 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1182 CBOR_TAG_INVALID16,
1183 CBOR_TAG_INVALID16,
1184 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001185
Laurence Lundblade9b334962020-08-27 10:55:53 -07001186 QCBORError uReturn = QCBOR_SUCCESS;
1187
Laurence Lundblade59289e52019-12-30 13:44:37 -08001188 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001189 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001190 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1191 if(uErr != QCBOR_SUCCESS) {
1192 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001193 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001194 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001195
Laurence Lundblade9b334962020-08-27 10:55:53 -07001196 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001197 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001198 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001199 break;
1200 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001201
Laurence Lundblade9b334962020-08-27 10:55:53 -07001202 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1203 // No room in the tag list
1204 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1205 // Continue on to get all tags on this item even though
1206 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001207 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001208 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001209 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001210 // Slide tags over one in the array to make room at index 0
1211 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1212 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001213 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001214
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001215 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001216 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001217 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001218 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001219 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001220 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001221 break;
1222 }
1223 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1224 break;
1225 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001226 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001227 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1228 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001229 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1230 // Continue on to get all tags on this item even though
1231 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001232 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001233 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001234 }
1235
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001236 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001237 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001238 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001239
1240 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001241 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001242 }
1243 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001244
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001245Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001246 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001247}
1248
1249
1250/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001251 This layer takes care of map entries. It combines the label and data
1252 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001253
1254 @retval QCBOR_ERR_UNSUPPORTED
1255
1256 @retval QCBOR_ERR_HIT_END
1257
1258 @retval QCBOR_ERR_INT_OVERFLOW
1259
1260 @retval QCBOR_ERR_STRING_ALLOCATE
1261
1262 @retval QCBOR_ERR_STRING_TOO_LONG
1263
1264 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1265
1266 @retval QCBOR_ERR_BAD_TYPE_7
1267
1268 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1269
1270 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1271
1272 @retval QCBOR_ERR_TOO_MANY_TAGS
1273
1274 @retval QCBOR_ERR_MAP_LABEL_TYPE
1275
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001276 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001277 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001278static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001279GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001280{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001281 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001282 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001283 if(nReturn)
1284 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001285
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001286 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001287 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001288 goto Done;
1289 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001290
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001291 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1292 // In a map and caller wants maps decoded, not treated as arrays
1293
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001294 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001295 // If in a map and the right decoding mode, get the label
1296
Laurence Lundbladeee851742020-01-08 08:37:05 -08001297 // Save label in pDecodedItem and get the next which will
1298 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001299 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001300 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001301 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001302 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001303 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001304
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301305 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001306
1307 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1308 // strings are always good labels
1309 pDecodedItem->label.string = LabelItem.val.string;
1310 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1311 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001312 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001313 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1314 goto Done;
1315 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1316 pDecodedItem->label.int64 = LabelItem.val.int64;
1317 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1318 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1319 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1320 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1321 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1322 pDecodedItem->label.string = LabelItem.val.string;
1323 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1324 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1325 } else {
1326 // label is not an int or a string. It is an arrray
1327 // or a float or such and this implementation doesn't handle that.
1328 // Also, tags on labels are ignored.
1329 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1330 goto Done;
1331 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001332 }
1333 } else {
1334 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001335 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001336 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001337 goto Done;
1338 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001339 // Decoding a map as an array
1340 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001341 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1342 // Cast is needed because of integer promotion
1343 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001344 }
1345 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001346
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001347Done:
1348 return nReturn;
1349}
1350
1351
Laurence Lundblade02625d42020-06-25 14:41:41 -07001352/*
1353 See if next item is a CBOR break. If it is, it is consumed,
1354 if not it is not consumed.
1355*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001356static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001357NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1358{
1359 *pbNextIsBreak = false;
1360 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001361 QCBORItem Peek;
1362 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1363 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1364 if(uReturn != QCBOR_SUCCESS) {
1365 return uReturn;
1366 }
1367 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001368 // It is not a break, rewind so it can be processed normally.
1369 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001370 } else {
1371 *pbNextIsBreak = true;
1372 }
1373 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001374
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001375 return QCBOR_SUCCESS;
1376}
1377
1378
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001379/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001380 An item was just consumed, now figure out if it was the
1381 end of an array or map that can be closed out. That
1382 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001383*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001384static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001385{
1386 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001387
Laurence Lundblade642282a2020-06-23 12:00:33 -07001388 /* This loops ascending nesting levels as long as there is ascending to do */
1389 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1390
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001391 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001392 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001393 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1394 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001395 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001396 break;
1397 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07001398 /* All of a definite length array was consumed; fall through to
1399 ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001400
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001401 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001402 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001403 bool bIsBreak = false;
1404 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1405 if(uReturn != QCBOR_SUCCESS) {
1406 goto Done;
1407 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001408
1409 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001410 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001411 break;
1412 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001413
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001414 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001415 /*
1416 Break occurred inside a bstr-wrapped CBOR or
1417 in the top level sequence. This is always an
1418 error because neither are an indefinte length
1419 map/array.
1420 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001421 uReturn = QCBOR_ERR_BAD_BREAK;
1422 goto Done;
1423 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001424
Laurence Lundblade02625d42020-06-25 14:41:41 -07001425 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001426 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001427
Laurence Lundblade02625d42020-06-25 14:41:41 -07001428 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001429
Laurence Lundblade93d89472020-10-03 22:30:50 -07001430 /* But ascent in bounded mode is only by explicit call to
1431 QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001432 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001433 /* Set the count to zero for definite length arrays to indicate
1434 cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001435 if(bMarkEnd) {
1436 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001437 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001438
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001439 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001440 break;
1441 }
1442
1443 /* Finally, actually ascend one level. */
1444 DecodeNesting_Ascend(&(pMe->nesting));
1445 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001446
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001447 uReturn = QCBOR_SUCCESS;
1448
1449Done:
1450 return uReturn;
1451}
1452
1453
1454/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001455 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001456 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1457 indefinte length maps and arrays by looking at the item count or
1458 finding CBOR breaks. It detects the ends of the top-level sequence
1459 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001460
1461 @retval QCBOR_ERR_UNSUPPORTED X
1462
1463 @retval QCBOR_ERR_HIT_END
1464
1465 @retval QCBOR_ERR_INT_OVERFLOW X
1466
1467 @retval QCBOR_ERR_STRING_ALLOCATE
1468
1469 @retval QCBOR_ERR_STRING_TOO_LONG
1470
1471 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1472
1473 @retval QCBOR_ERR_BAD_TYPE_7 X
1474
1475 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1476
1477 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1478
1479 @retval QCBOR_ERR_TOO_MANY_TAGS
1480
1481 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1482
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001483 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001484
1485 @retval QCBOR_ERR_NO_MORE_ITEMS
1486
1487 @retval QCBOR_ERR_BAD_BREAK
1488
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001489 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001490static QCBORError
1491QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001492{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001493 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001494 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001495
Laurence Lundblade642282a2020-06-23 12:00:33 -07001496 /*
1497 If out of bytes to consume, it is either the end of the top-level
1498 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001499
Laurence Lundblade642282a2020-06-23 12:00:33 -07001500 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1501 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1502 CBOR is exited, the length is set back to the top-level's length
1503 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001504 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001505 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001506 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001507 goto Done;
1508 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001509
Laurence Lundblade642282a2020-06-23 12:00:33 -07001510 /*
1511 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001512 array. The check for the end of an indefinite length array is
1513 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001514 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001515 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001516 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001517 goto Done;
1518 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001519
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001520 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001521 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001522 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1523 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001524 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001525 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301526
Laurence Lundblade642282a2020-06-23 12:00:33 -07001527 /*
1528 Breaks ending arrays/maps are always processed at the end of this
1529 function. They should never show up here.
1530 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301531 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001532 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301533 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301534 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001535
Laurence Lundblade642282a2020-06-23 12:00:33 -07001536 /*
1537 Record the nesting level for this data item before processing any
1538 of decrementing and descending.
1539 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001540 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001541
Laurence Lundblade642282a2020-06-23 12:00:33 -07001542
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001543 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001544 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001545 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001546 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001547
Laurence Lundblade93d89472020-10-03 22:30:50 -07001548 Empty indefinite length maps and arrays are descended into, but
1549 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001550
1551 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001552 encloses them so a decrement needs to be done for them too, but
1553 that is done only when all the items in them have been
1554 processed, not when they are opened with the exception of an
1555 empty map or array.
1556 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001557 QCBORError uDescendErr;
1558 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001559 pDecodedItem->uDataType,
1560 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001561 if(uDescendErr != QCBOR_SUCCESS) {
1562 /* This error is probably a traversal error and it
1563 overrides the non-traversal error. */
1564 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001565 goto Done;
1566 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001567 }
1568
Laurence Lundblade02625d42020-06-25 14:41:41 -07001569 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1570 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1571 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001572 /*
1573 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001574 - A non-aggregate like an integer or string
1575 - An empty definite length map or array
1576 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001577
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001578 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001579 definite length map/array and break detection for an indefinite
1580 length map/array. If the end of the map/array was reached, then
1581 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001582 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001583 QCBORError uAscendErr;
1584 uAscendErr = NestLevelAscender(me, true);
1585 if(uAscendErr != QCBOR_SUCCESS) {
1586 /* This error is probably a traversal error and it
1587 overrides the non-traversal error. */
1588 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001589 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001590 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301591 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001592
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001593 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001594 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001595 Tell the caller what level is next. This tells them what
1596 maps/arrays were closed out and makes it possible for them to
1597 reconstruct the tree with just the information returned in
1598 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001599 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001600 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001601 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001602 pDecodedItem->uNextNestLevel = 0;
1603 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001604 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001605 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001606
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001607Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001608 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001609}
1610
Laurence Lundblade9b334962020-08-27 10:55:53 -07001611static void ShiftTags(QCBORItem *pDecodedItem)
1612{
1613 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1614 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1615 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1616 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1617}
1618
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001619
Laurence Lundblade59289e52019-12-30 13:44:37 -08001620/*
1621 Mostly just assign the right data type for the date string.
1622 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001623static inline QCBORError DecodeDateString(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001624{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001625 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1626 return QCBOR_ERR_BAD_OPT_TAG;
1627 }
1628
1629 const UsefulBufC Temp = pDecodedItem->val.string;
1630 pDecodedItem->val.dateString = Temp;
1631 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001632 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001633 return QCBOR_SUCCESS;
1634}
1635
1636
Laurence Lundblade9b334962020-08-27 10:55:53 -07001637
Laurence Lundblade59289e52019-12-30 13:44:37 -08001638/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001639 The epoch formatted date. Turns lots of different forms of encoding
1640 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001641 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001642static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001643{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001644 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001645
1646 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1647
1648 switch (pDecodedItem->uDataType) {
1649
1650 case QCBOR_TYPE_INT64:
1651 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1652 break;
1653
1654 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001655 // This only happens for CBOR type 0 > INT64_MAX so it is
1656 // always an overflow.
1657 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1658 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001659 break;
1660
1661 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001662 case QCBOR_TYPE_FLOAT:
1663#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001664 {
1665 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001666 // conversion to an int64_t to be able to detect doubles that
1667 // are too large to fit into an int64_t. A double has 52
1668 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1669 // to a double actually causes a round up which is bad and
1670 // wrong for the comparison because it will allow conversion
1671 // of doubles that can't fit into a uint64_t. To remedy this
1672 // INT64_MAX - 0x7ff is used as the cutoff point because if
1673 // that value rounds up in conversion to double it will still
1674 // be less than INT64_MAX. 0x7ff is picked because it has 11
1675 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001676 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001677 // INT64_MAX seconds is on the order of 10 billion years, and
1678 // the earth is less than 5 billion years old, so for most
1679 // uses this conversion error won't occur even though doubles
1680 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001681 //
1682 // Without the 0x7ff there is a ~30 minute range of time
1683 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001684 // where this code would go wrong. Some compilers
1685 // will generate warnings or errors without the 0x7ff
1686 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001687 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1688 pDecodedItem->val.dfnum :
1689 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001690 if(isnan(d) ||
1691 d > (double)(INT64_MAX - 0x7ff) ||
1692 d < (double)(INT64_MIN + 0x7ff)) {
1693 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001694 goto Done;
1695 }
1696 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001697 pDecodedItem->val.epochDate.fSecondsFraction =
1698 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001699 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001700#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001701
Laurence Lundbladec7114722020-08-13 05:11:40 -07001702 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001703 goto Done;
1704
Laurence Lundblade9682a532020-06-06 18:33:04 -07001705#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001706 break;
1707
1708 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001709 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001710 goto Done;
1711 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001712
Laurence Lundblade59289e52019-12-30 13:44:37 -08001713 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1714
1715Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001716 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001717}
1718
1719
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001720/*
1721 Mostly just assign the right data type for the bignum.
1722 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001723static inline QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001724{
1725 // Stack Use: UsefulBuf 1 -- 16
1726 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1727 return QCBOR_ERR_BAD_OPT_TAG;
1728 }
1729 const UsefulBufC Temp = pDecodedItem->val.string;
1730 pDecodedItem->val.bigNum = Temp;
1731 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1732 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1733 : QCBOR_TYPE_NEGBIGNUM);
1734 return QCBOR_SUCCESS;
1735}
1736
1737
Laurence Lundblade59289e52019-12-30 13:44:37 -08001738#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1739/*
1740 Decode decimal fractions and big floats.
1741
1742 When called pDecodedItem must be the array that is tagged as a big
1743 float or decimal fraction, the array that has the two members, the
1744 exponent and mantissa.
1745
1746 This will fetch and decode the exponent and mantissa and put the
1747 result back into pDecodedItem.
1748 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001749static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001750QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1751{
1752 QCBORError nReturn;
1753
1754 // --- Make sure it is an array; track nesting level of members ---
1755 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1756 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1757 goto Done;
1758 }
1759
1760 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001761 // definite length arrays, but not for indefnite. Instead remember
1762 // the nesting level the two integers must be at, which is one
1763 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001764 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1765
1766 // --- Is it a decimal fraction or a bigfloat? ---
1767 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1768 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1769
1770 // --- Get the exponent ---
1771 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001772 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001773 if(nReturn != QCBOR_SUCCESS) {
1774 goto Done;
1775 }
1776 if(exponentItem.uNestingLevel != nNestLevel) {
1777 // Array is empty or a map/array encountered when expecting an int
1778 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1779 goto Done;
1780 }
1781 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1782 // Data arriving as an unsigned int < INT64_MAX has been converted
1783 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1784 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1785 // will be too large for this to handle and thus an error that will
1786 // get handled in the next else.
1787 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1788 } else {
1789 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1790 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1791 goto Done;
1792 }
1793
1794 // --- Get the mantissa ---
1795 QCBORItem mantissaItem;
1796 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1797 if(nReturn != QCBOR_SUCCESS) {
1798 goto Done;
1799 }
1800 if(mantissaItem.uNestingLevel != nNestLevel) {
1801 // Mantissa missing or map/array encountered when expecting number
1802 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1803 goto Done;
1804 }
1805 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1806 // Data arriving as an unsigned int < INT64_MAX has been converted
1807 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1808 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1809 // will be too large for this to handle and thus an error that
1810 // will get handled in an else below.
1811 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001812 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1813 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001814 // Got a good big num mantissa
1815 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1816 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001817 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1818 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1819 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001820 } else {
1821 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1822 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1823 goto Done;
1824 }
1825
1826 // --- Check that array only has the two numbers ---
1827 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001828 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001829 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1830 goto Done;
1831 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001832 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001833
1834Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001835 return nReturn;
1836}
1837#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1838
1839
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001840static inline QCBORError DecodeURI(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001841{
1842 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1843 return QCBOR_ERR_BAD_OPT_TAG;
1844 }
1845 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1846 return QCBOR_SUCCESS;
1847}
1848
1849
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001850static inline QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001851{
1852 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1853 return QCBOR_ERR_BAD_OPT_TAG;
1854 }
1855 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001856
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001857 return QCBOR_SUCCESS;
1858}
1859
1860
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001861static inline QCBORError DecodeB64(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001862{
1863 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1864 return QCBOR_ERR_BAD_OPT_TAG;
1865 }
1866 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001867
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001868 return QCBOR_SUCCESS;
1869}
1870
1871
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001872static inline QCBORError DecodeRegex(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001873{
1874 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1875 return QCBOR_ERR_BAD_OPT_TAG;
1876 }
1877 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001878
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001879 return QCBOR_SUCCESS;
1880}
1881
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001882
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001883static inline QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001884{
1885 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1886 return QCBOR_ERR_BAD_OPT_TAG;
1887 }
1888 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001889
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001890 return QCBOR_SUCCESS;
1891}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001892
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001893
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001894static inline QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001895{
1896 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1897 return QCBOR_ERR_BAD_OPT_TAG;
1898 }
1899 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001900
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001901 return QCBOR_SUCCESS;
1902}
1903
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001904
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001905static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001906{
1907 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1908 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001909 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001910 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1911 } else {
1912 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001913
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001914 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001915
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001916 return QCBOR_SUCCESS;
1917}
1918
1919
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001920static inline QCBORError DecodeUUID(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001921{
1922 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1923 return QCBOR_ERR_BAD_OPT_TAG;
1924 }
1925 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001926
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001927 return QCBOR_SUCCESS;
1928}
1929
1930
Laurence Lundblade59289e52019-12-30 13:44:37 -08001931/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001932 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001933 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001934static QCBORError
1935QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001936{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001937 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001938
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001939 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
1940 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001941 goto Done;
1942 }
1943
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001944 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
1945 switch(pDecodedItem->uTags[uTagIndex]) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001946
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001947 // Many of the functions here only just map a CBOR tag to
1948 // a QCBOR_TYPE for a string and could probably be
1949 // implemented with less object code. This implementation
1950 // of string types takes about 120 bytes of object code
1951 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001952 case CBOR_TAG_DATE_STRING:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001953 uReturn = DecodeDateString(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001954 break;
1955
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001956 case CBOR_TAG_DATE_EPOCH:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001957 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001958 break;
1959
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001960 case CBOR_TAG_POS_BIGNUM:
1961 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001962 uReturn = DecodeBigNum(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001963 break;
1964
Laurence Lundblade93d89472020-10-03 22:30:50 -07001965#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001966 case CBOR_TAG_DECIMAL_FRACTION:
1967 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001968 // For aggregate tagged types, what goes into pTags is only collected
1969 // from the surrounding data item, not the contents, so pTags is not
1970 // passed on here.
1971
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001972 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001973 break;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001974#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001975
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001976 case CBOR_TAG_CBOR:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001977 uReturn = DecodeWrappedCBOR(pDecodedItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001978 break;
1979
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001980 case CBOR_TAG_CBOR_SEQUENCE:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001981 uReturn = DecodeWrappedCBORSequence(pDecodedItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001982 break;
1983
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001984 case CBOR_TAG_URI:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001985 uReturn = DecodeURI(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001986 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001987
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001988 case CBOR_TAG_B64URL:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001989 uReturn = DecodeB64URL(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001990 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001991
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001992 case CBOR_TAG_B64:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001993 uReturn = DecodeB64(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001994 break;
1995
1996 case CBOR_TAG_MIME:
1997 case CBOR_TAG_BINARY_MIME:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001998 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001999 break;
2000
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002001 case CBOR_TAG_REGEX:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002002 uReturn = DecodeRegex(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002003 break;
2004
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002005 case CBOR_TAG_BIN_UUID:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002006 uReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002007 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002008
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002009 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002010 // The end of the tag list or no tags
2011 // Successful exit from the loop.
2012 goto Done;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002013
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002014 default:
2015 // A tag that is not understood
2016 // A successful exit from the loop
2017 goto Done;
2018
2019 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002020 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002021 goto Done;
2022 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002023 // A tag was successfully processed, shift it
2024 // out of the list of tags returned.
2025 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002026 }
2027
2028Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002029 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002030}
2031
2032
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002033/*
2034 Public function, see header qcbor/qcbor_decode.h file
2035 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002036QCBORError
2037QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2038{
2039 QCBORError uErr;
2040 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2041 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002042 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2043 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2044 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002045 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002046}
2047
2048
2049/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002050 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002051 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002052QCBORError
2053QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2054{
2055 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2056 const UsefulInputBuf Save = pMe->InBuf;
2057
2058 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2059
2060 pMe->nesting = SaveNesting;
2061 pMe->InBuf = Save;
2062
2063 return uErr;
2064}
2065
2066
2067/*
2068 Public function, see header qcbor/qcbor_decode.h file
2069 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002070void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2071{
2072 if(pMe->uLastError != QCBOR_SUCCESS) {
2073 return;
2074 }
2075
2076 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2077}
2078
2079
2080/*
2081 Public function, see header qcbor/qcbor_decode.h file
2082 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002083QCBORError
2084QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2085 QCBORItem *pDecodedItem,
2086 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002087{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002088 QCBORError nReturn;
2089
2090 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2091 if(nReturn != QCBOR_SUCCESS) {
2092 return nReturn;
2093 }
2094
2095 if(pTags != NULL) {
2096 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002097 // Reverse the order because pTags is reverse of
2098 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002099 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2100 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002101 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002102 }
2103 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2104 return QCBOR_ERR_TOO_MANY_TAGS;
2105 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002106 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002107 pTags->uNumUsed++;
2108 }
2109 }
2110
2111 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002112}
2113
2114
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002115/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302116 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302117 next one down. If a layer has no work to do for a particular item
2118 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002119
Laurence Lundblade59289e52019-12-30 13:44:37 -08002120 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2121 tagged data items, turning them into the local C representation.
2122 For the most simple it is just associating a QCBOR_TYPE with the data. For
2123 the complex ones that an aggregate of data items, there is some further
2124 decoding and a little bit of recursion.
2125
2126 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302127 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302128 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002129 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002130
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302131 - GetNext_MapEntry -- This handles the combining of two
2132 items, the label and the data, that make up a map entry.
2133 It only does work on maps. It combines the label and data
2134 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002135
Laurence Lundblade59289e52019-12-30 13:44:37 -08002136 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2137 tags into bit flags associated with the data item. No actual decoding
2138 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002139
Laurence Lundblade59289e52019-12-30 13:44:37 -08002140 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302141 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302142 string allocater to create contiguous space for the item. It
2143 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002144
Laurence Lundblade59289e52019-12-30 13:44:37 -08002145 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2146 atomic data item has a "major type", an integer "argument" and optionally
2147 some content. For text and byte strings, the content is the bytes
2148 that make up the string. These are the smallest data items that are
2149 considered to be well-formed. The content may also be other data items in
2150 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002151
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002152 Roughly this takes 300 bytes of stack for vars. Need to
2153 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002154
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302155 */
2156
2157
2158/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002159 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002160 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002161bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002162 const QCBORItem *pItem,
2163 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002164{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002165 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2166 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002167 break;
2168 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002169 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002170 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002171 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002172 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002173
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002174 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002175}
2176
2177
2178/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002179 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002180 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002181QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002182{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002183 QCBORError uReturn = me->uLastError;
2184
2185 if(uReturn != QCBOR_SUCCESS) {
2186 goto Done;
2187 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002188
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002189 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002190 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002191 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002192 goto Done;
2193 }
2194
2195 // Error out if not all the bytes are consumed
2196 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002197 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002198 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002199
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002200Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302201 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002202 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002203 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002204
Laurence Lundblade085d7952020-07-24 10:26:30 -07002205 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002206}
2207
2208
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002209/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002210 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002211*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002212// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002213uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2214 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002215 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002216{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002217 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2218 return CBOR_TAG_INVALID64;
2219 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002220 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2221 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002222 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002223 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002224 }
2225}
2226
Laurence Lundblade9b334962020-08-27 10:55:53 -07002227/*
2228 Public function, see header qcbor/qcbor_decode.h file
2229*/
2230uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2231 uint32_t uIndex)
2232{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002233 if(pMe->uLastError != QCBOR_SUCCESS) {
2234 return CBOR_TAG_INVALID64;
2235 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002236 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2237 return CBOR_TAG_INVALID64;
2238 } else {
2239 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2240 }
2241}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002242
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002243/*
2244
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002245Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002246
Laurence Lundbladeee851742020-01-08 08:37:05 -08002247 - Hit end of input before it was expected while decoding type and
2248 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002249
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002250 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002251
Laurence Lundbladeee851742020-01-08 08:37:05 -08002252 - Hit end of input while decoding a text or byte string
2253 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002254
Laurence Lundbladeee851742020-01-08 08:37:05 -08002255 - Encountered conflicting tags -- e.g., an item is tagged both a date
2256 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002257
Laurence Lundbladeee851742020-01-08 08:37:05 -08002258 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002259 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002260
Laurence Lundbladeee851742020-01-08 08:37:05 -08002261 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002262 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002263
Laurence Lundbladeee851742020-01-08 08:37:05 -08002264 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2265 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002266
Laurence Lundbladeee851742020-01-08 08:37:05 -08002267 - The type of a map label is not a string or int
2268 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002269
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002270 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002271
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002272 */
2273
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002274
2275
Laurence Lundbladef6531662018-12-04 10:42:22 +09002276
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002277/* ===========================================================================
2278 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002279
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002280 This implements a simple sting allocator for indefinite length
2281 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2282 implements the function type QCBORStringAllocate and allows easy
2283 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002284
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002285 This particular allocator is built-in for convenience. The caller
2286 can implement their own. All of this following code will get
2287 dead-stripped if QCBORDecode_SetMemPool() is not called.
2288
2289 This is a very primitive memory allocator. It does not track
2290 individual allocations, only a high-water mark. A free or
2291 reallocation must be of the last chunk allocated.
2292
2293 The size of the pool and offset to free memory are packed into the
2294 first 8 bytes of the memory pool so we don't have to keep them in
2295 the decode context. Since the address of the pool may not be
2296 aligned, they have to be packed and unpacked as if they were
2297 serialized data of the wire or such.
2298
2299 The sizes packed in are uint32_t to be the same on all CPU types
2300 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002301 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002302
2303
Laurence Lundbladeee851742020-01-08 08:37:05 -08002304static inline int
2305MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002306{
2307 // Use of UsefulInputBuf is overkill, but it is convenient.
2308 UsefulInputBuf UIB;
2309
Laurence Lundbladeee851742020-01-08 08:37:05 -08002310 // Just assume the size here. It was checked during SetUp so
2311 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002312 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002313 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2314 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2315 return UsefulInputBuf_GetError(&UIB);
2316}
2317
2318
Laurence Lundbladeee851742020-01-08 08:37:05 -08002319static inline int
2320MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002321{
2322 // Use of UsefulOutBuf is overkill, but convenient. The
2323 // length check performed here is useful.
2324 UsefulOutBuf UOB;
2325
2326 UsefulOutBuf_Init(&UOB, Pool);
2327 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2328 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2329 return UsefulOutBuf_GetError(&UOB);
2330}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002331
2332
2333/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002334 Internal function for an allocation, reallocation free and destuct.
2335
2336 Having only one function rather than one each per mode saves space in
2337 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002338
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002339 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2340 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002341static UsefulBuf
2342MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002343{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002344 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002345
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002346 uint32_t uPoolSize;
2347 uint32_t uFreeOffset;
2348
2349 if(uNewSize > UINT32_MAX) {
2350 // This allocator is only good up to 4GB. This check should
2351 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2352 goto Done;
2353 }
2354 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2355
2356 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2357 goto Done;
2358 }
2359
2360 if(uNewSize) {
2361 if(pMem) {
2362 // REALLOCATION MODE
2363 // Calculate pointer to the end of the memory pool. It is
2364 // assumed that pPool + uPoolSize won't wrap around by
2365 // assuming the caller won't pass a pool buffer in that is
2366 // not in legitimate memory space.
2367 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2368
2369 // Check that the pointer for reallocation is in the range of the
2370 // pool. This also makes sure that pointer math further down
2371 // doesn't wrap under or over.
2372 if(pMem >= pPool && pMem < pPoolEnd) {
2373 // Offset to start of chunk for reallocation. This won't
2374 // wrap under because of check that pMem >= pPool. Cast
2375 // is safe because the pool is always less than UINT32_MAX
2376 // because of check in QCBORDecode_SetMemPool().
2377 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2378
2379 // Check to see if the allocation will fit. uPoolSize -
2380 // uMemOffset will not wrap under because of check that
2381 // pMem is in the range of the uPoolSize by check above.
2382 if(uNewSize <= uPoolSize - uMemOffset) {
2383 ReturnValue.ptr = pMem;
2384 ReturnValue.len = uNewSize;
2385
2386 // Addition won't wrap around over because uNewSize was
2387 // checked to be sure it is less than the pool size.
2388 uFreeOffset = uMemOffset + uNewSize32;
2389 }
2390 }
2391 } else {
2392 // ALLOCATION MODE
2393 // uPoolSize - uFreeOffset will not underflow because this
2394 // pool implementation makes sure uFreeOffset is always
2395 // smaller than uPoolSize through this check here and
2396 // reallocation case.
2397 if(uNewSize <= uPoolSize - uFreeOffset) {
2398 ReturnValue.len = uNewSize;
2399 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002400 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002401 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002402 }
2403 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002404 if(pMem) {
2405 // FREE MODE
2406 // Cast is safe because of limit on pool size in
2407 // QCBORDecode_SetMemPool()
2408 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2409 } else {
2410 // DESTRUCT MODE
2411 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002412 }
2413 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002414
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002415 UsefulBuf Pool = {pPool, uPoolSize};
2416 MemPool_Pack(Pool, uFreeOffset);
2417
2418Done:
2419 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002420}
2421
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002422
Laurence Lundbladef6531662018-12-04 10:42:22 +09002423/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002424 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002425 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002426QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2427 UsefulBuf Pool,
2428 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002429{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002430 // The pool size and free mem offset are packed into the beginning
2431 // of the pool memory. This compile time check make sure the
2432 // constant in the header is correct. This check should optimize
2433 // down to nothing.
2434 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002435 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002436 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002437
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002438 // The pool size and free offset packed in to the beginning of pool
2439 // memory are only 32-bits. This check will optimize out on 32-bit
2440 // machines.
2441 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002442 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002443 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002444
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002445 // This checks that the pool buffer given is big enough.
2446 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002447 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002448 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002449
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002450 pMe->StringAllocator.pfAllocator = MemPool_Function;
2451 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2452 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002453
Laurence Lundblade30816f22018-11-10 13:40:22 +07002454 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002455}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002456
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002457
2458
Laurence Lundblade9b334962020-08-27 10:55:53 -07002459static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2460{
2461 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2462}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002463
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002464
2465/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002466 Consume an entire map or array (and do next to
2467 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002468 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002469static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002470ConsumeItem(QCBORDecodeContext *pMe,
2471 const QCBORItem *pItemToConsume,
2472 uint_fast8_t *puNextNestLevel)
2473{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002474 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002475 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002476
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002477 // If it is a map or array, this will tell if it is empty.
2478 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2479
2480 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2481 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002482
Laurence Lundblade1341c592020-04-11 14:19:05 -07002483 /* This works for definite and indefinite length
2484 * maps and arrays by using the nesting level
2485 */
2486 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002487 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002488 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002489 goto Done;
2490 }
2491 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002492
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002493 *puNextNestLevel = Item.uNextNestLevel;
2494
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002495 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002496
Laurence Lundblade1341c592020-04-11 14:19:05 -07002497 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002498 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002499 /* Just pass the nesting level through */
2500 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2501
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002502 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002503 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002504
2505Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002506 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002507}
2508
2509
Laurence Lundblade1341c592020-04-11 14:19:05 -07002510/* Return true if the labels in Item1 and Item2 are the same.
2511 Works only for integer and string labels. Returns false
2512 for any other type. */
2513static inline bool
2514MatchLabel(QCBORItem Item1, QCBORItem Item2)
2515{
2516 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2517 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2518 return true;
2519 }
2520 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002521 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002522 return true;
2523 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002524 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002525 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2526 return true;
2527 }
2528 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2529 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2530 return true;
2531 }
2532 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002533
Laurence Lundblade1341c592020-04-11 14:19:05 -07002534 /* Other label types are never matched */
2535 return false;
2536}
2537
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002538
2539/*
2540 Returns true if Item1 and Item2 are the same type
2541 or if either are of QCBOR_TYPE_ANY.
2542 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002543static inline bool
2544MatchType(QCBORItem Item1, QCBORItem Item2)
2545{
2546 if(Item1.uDataType == Item2.uDataType) {
2547 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002548 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002549 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002550 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002551 return true;
2552 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002553 return false;
2554}
2555
2556
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002557/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002558 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002559
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002560 @param[in] pMe The decode context to search.
2561 @param[in,out] pItemArray The items to search for and the items found.
2562 @param[out] puOffset Byte offset of last item matched.
2563 @param[in] pCBContext Context for the not-found item call back.
2564 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002565
2566 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2567
Laurence Lundblade93d89472020-10-03 22:30:50 -07002568 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2569 were found for one of the labels being
2570 search for. This duplicate detection is
2571 only performed for items in pItemArray,
2572 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002573
Laurence Lundblade93d89472020-10-03 22:30:50 -07002574 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2575 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002576
2577 @retval Also errors returned by QCBORDecode_GetNext().
2578
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002579 On input pItemArray contains a list of labels and data types
2580 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002581
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002582 On output the fully retrieved items are filled in with
2583 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002584
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002585 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002586
2587 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002588 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002589static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002590MapSearch(QCBORDecodeContext *pMe,
2591 QCBORItem *pItemArray,
2592 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002593 void *pCBContext,
2594 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002595{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002596 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002597 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002598
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002599 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002600 uReturn = pMe->uLastError;
2601 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002602 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002603
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002604 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002605 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2606 /* QCBOR_TYPE_NONE as first item indicates just looking
2607 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002608 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2609 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002610 }
2611
Laurence Lundblade085d7952020-07-24 10:26:30 -07002612 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2613 // It is an empty bounded array or map
2614 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2615 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002616 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002617 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002618 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002619 // Nothing is ever found in an empty array or map. All items
2620 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002621 uReturn = QCBOR_SUCCESS;
2622 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002623 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002624 }
2625
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002626 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002627 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2628
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002629 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002630 UsefulInputBuf_Seek(&(pMe->InBuf),
2631 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002632
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002633 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002634 Loop over all the items in the map or array. Each item
2635 could be a map or array, but label matching is only at
2636 the main level. This handles definite and indefinite
2637 length maps and arrays. The only reason this is ever
2638 called on arrays is to find their end position.
2639
2640 This will always run over all items in order to do
2641 duplicate detection.
2642
2643 This will exit with failure if it encounters an
2644 unrecoverable error, but continue on for recoverable
2645 errors.
2646
2647 If a recoverable error occurs on a matched item, then
2648 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002649 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002650 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002651 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002652 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002653 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002654 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002655
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002656 /* Get the item */
2657 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002658 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2659 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002660 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002661 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002662 goto Done;
2663 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002664 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002665 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002666 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002667 goto Done;
2668 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002669
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002670 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002671 bool bMatched = false;
2672 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2673 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002674 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002675 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2676 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002677 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002678 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002679 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002680 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002681 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002682 goto Done;
2683 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002684
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002685 if(uResult != QCBOR_SUCCESS) {
2686 uReturn = uResult;
2687 goto Done;
2688 }
2689
Laurence Lundblade1341c592020-04-11 14:19:05 -07002690 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002691 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002692 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002693 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002694 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002695 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002696 bMatched = true;
2697 }
2698 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002699
2700
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002701 if(!bMatched && pfCallback != NULL) {
2702 /*
2703 Call the callback on unmatched labels.
2704 (It is tempting to do duplicate detection here, but that would
2705 require dynamic memory allocation because the number of labels
2706 that might be encountered is unbounded.)
2707 */
2708 uReturn = (*pfCallback)(pCBContext, &Item);
2709 if(uReturn != QCBOR_SUCCESS) {
2710 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002711 }
2712 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002713
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002714 /*
2715 Consume the item whether matched or not. This
2716 does the work of traversing maps and array and
2717 everything in them. In this loop only the
2718 items at the current nesting level are examined
2719 to match the labels.
2720 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002721 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002722 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002723 goto Done;
2724 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002725
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002726 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002727
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002728 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002729
2730 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002731
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002732 // Check here makes sure that this won't accidentally be
2733 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002734 // QCBOR_MAX_DECODE_INPUT_SIZE.
2735 if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
2736 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2737 goto Done;
2738 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002739 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2740 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002741
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002742 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002743 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2744
2745 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002746 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002747 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002748 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002749 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2750 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002751 }
2752 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002753
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002754 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002755}
2756
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002757
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002758/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002759 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002760*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002761void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2762 int64_t nLabel,
2763 uint8_t uQcborType,
2764 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002765{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002766 if(pMe->uLastError != QCBOR_SUCCESS) {
2767 return;
2768 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002769
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002770 QCBORItem OneItemSeach[2];
2771 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2772 OneItemSeach[0].label.int64 = nLabel;
2773 OneItemSeach[0].uDataType = uQcborType;
2774 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002775
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002776 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002777
2778 *pItem = OneItemSeach[0];
2779
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002780 if(uReturn != QCBOR_SUCCESS) {
2781 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002782 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002783 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002784 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002785 }
2786
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002787 Done:
2788 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002789}
2790
2791
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002792/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002793 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002794*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002795void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2796 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002797 uint8_t uQcborType,
2798 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002799{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002800 if(pMe->uLastError != QCBOR_SUCCESS) {
2801 return;
2802 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002803
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002804 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002805 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2806 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2807 OneItemSeach[0].uDataType = uQcborType;
2808 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002809
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002810 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2811 if(uReturn != QCBOR_SUCCESS) {
2812 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002813 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002814 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002815 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002816 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002817 }
2818
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002819 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002820
2821Done:
2822 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002823}
2824
2825
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002826
Laurence Lundblade93d89472020-10-03 22:30:50 -07002827static QCBORError
2828CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002829{
2830 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2831 if(uDataType == puTypeList[i]) {
2832 return QCBOR_SUCCESS;
2833 }
2834 }
2835 return QCBOR_ERR_UNEXPECTED_TYPE;
2836}
2837
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002838
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002839/**
2840 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002841 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002842
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002843 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2844 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002845
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002846 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2847 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002848 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002849static QCBORError
2850CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002851{
2852 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2853 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2854 /* There are tags that QCBOR couldn't process on this item and
2855 the caller has told us there should not be. */
2856 return QCBOR_ERR_UNEXPECTED_TYPE;
2857 }
2858
2859 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2860 const int nItemType = pItem->uDataType;
2861
2862 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2863 // Must match the tag and only the tag
2864 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2865 }
2866
2867 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2868 if(uReturn == QCBOR_SUCCESS) {
2869 return QCBOR_SUCCESS;
2870 }
2871
2872 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2873 /* Must match the content type and only the content type.
2874 There was no match just above so it is a fail. */
2875 return QCBOR_ERR_UNEXPECTED_TYPE;
2876 }
2877
2878 /* If here it can match either the tag or the content
2879 and it hasn't matched the content, so the end
2880 result is whether it matches the tag. This is
2881 also the case that the CBOR standard discourages. */
2882
2883 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2884}
2885
Laurence Lundblade9b334962020-08-27 10:55:53 -07002886
Laurence Lundblade9b334962020-08-27 10:55:53 -07002887
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002888// This could be semi-private if need be
2889static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002890void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2891 int64_t nLabel,
2892 TagSpecification TagSpec,
2893 QCBORItem *pItem)
2894{
2895 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2896 if(pMe->uLastError != QCBOR_SUCCESS) {
2897 return;
2898 }
2899
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002900 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002901}
2902
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002903
2904// This could be semi-private if need be
2905static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002906void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2907 const char *szLabel,
2908 TagSpecification TagSpec,
2909 QCBORItem *pItem)
2910{
2911 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2912 if(pMe->uLastError != QCBOR_SUCCESS) {
2913 return;
2914 }
2915
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002916 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002917}
2918
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002919// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002920void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2921 int64_t nLabel,
2922 TagSpecification TagSpec,
2923 UsefulBufC *pString)
2924{
2925 QCBORItem Item;
2926 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2927 if(pMe->uLastError == QCBOR_SUCCESS) {
2928 *pString = Item.val.string;
2929 }
2930}
2931
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002932// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002933void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2934 const char * szLabel,
2935 TagSpecification TagSpec,
2936 UsefulBufC *pString)
2937{
2938 QCBORItem Item;
2939 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2940 if(pMe->uLastError == QCBOR_SUCCESS) {
2941 *pString = Item.val.string;
2942 }
2943}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002944
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002945/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002946 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002947*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002948void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002949{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002950 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2951 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002952}
2953
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002954/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002955 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002956*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002957void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2958 QCBORItem *pItemList,
2959 void *pCallbackCtx,
2960 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002961{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002962 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2963 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002964}
2965
2966
Laurence Lundblade34691b92020-05-18 22:25:25 -07002967static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002968{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002969 // The first item in pSearch is the one that is to be
2970 // entered. It should be the only one filled in. Any other
2971 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07002972 if(pMe->uLastError != QCBOR_SUCCESS) {
2973 // Already in error state; do nothing.
2974 return;
2975 }
2976
2977 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002978 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002979 if(pMe->uLastError != QCBOR_SUCCESS) {
2980 return;
2981 }
2982
Laurence Lundblade9b334962020-08-27 10:55:53 -07002983 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002984 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002985 return;
2986 }
2987
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002988 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002989 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002990
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002991 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002992 be at the right place.
2993
2994 The UsefulInBuf offset could be anywhere, so no assumption is
2995 made about it.
2996
2997 No assumption is made about the pre-order nesting level either.
2998
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002999 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003000 the map level that is being entered.
3001 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003002 /* Seek to the data item that is the map or array */
3003 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003004
3005 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003006
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003007 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003008}
3009
3010
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003011/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003012 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003013*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003014void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003015{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003016 QCBORItem OneItemSeach[2];
3017 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3018 OneItemSeach[0].label.int64 = nLabel;
3019 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3020 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003021
Laurence Lundblade9b334962020-08-27 10:55:53 -07003022 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003023 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003024}
3025
3026
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003027/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003028 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003029*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003030void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003031{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003032 QCBORItem OneItemSeach[2];
3033 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3034 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3035 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3036 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003037
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003038 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003039}
3040
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003041/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003042 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003043*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003044void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003045{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003046 QCBORItem OneItemSeach[2];
3047 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3048 OneItemSeach[0].label.int64 = nLabel;
3049 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3050 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003051
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003052 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003053}
3054
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003055/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003056 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003057*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003058void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3059{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003060 QCBORItem OneItemSeach[2];
3061 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3062 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3063 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3064 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003065
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003066 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003067}
3068
3069
Laurence Lundblade02625d42020-06-25 14:41:41 -07003070// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003071void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003072{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003073 QCBORError uErr;
3074
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003075 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003076 if(pMe->uLastError != QCBOR_SUCCESS) {
3077 // Already in error state; do nothing.
3078 return;
3079 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003080
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003081 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003082 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003083 uErr = QCBORDecode_GetNext(pMe, &Item);
3084 if(uErr != QCBOR_SUCCESS) {
3085 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003086 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003087 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003088 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3089 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003090 }
3091
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003092 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003093
3094
Laurence Lundbladef0499502020-08-01 11:55:57 -07003095 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003096 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003097 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3098 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003099 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003100 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3101 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003102 // Special case to increment nesting level for zero-length maps
3103 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003104 DecodeNesting_Descend(&(pMe->nesting), uType);
3105 }
3106
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003107 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003108
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003109 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3110 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003111
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003112 if(pItem != NULL) {
3113 *pItem = Item;
3114 }
3115
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003116Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003117 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003118}
3119
Laurence Lundblade02625d42020-06-25 14:41:41 -07003120
3121/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003122 This is the common work for exiting a level that is a bounded map,
3123 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003124
3125 One chunk of work is to set up the pre-order traversal so it is at
3126 the item just after the bounded map, array or bstr that is being
3127 exited. This is somewhat complex.
3128
3129 The other work is to level-up the bounded mode to next higest bounded
3130 mode or the top level if there isn't one.
3131 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003132static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003133ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003134{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003135 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003136
Laurence Lundblade02625d42020-06-25 14:41:41 -07003137 /*
3138 First the pre-order-traversal byte offset is positioned to the
3139 item just after the bounded mode item that was just consumed.
3140 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003141 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3142
Laurence Lundblade02625d42020-06-25 14:41:41 -07003143 /*
3144 Next, set the current nesting level to one above the bounded level
3145 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003146
Laurence Lundblade02625d42020-06-25 14:41:41 -07003147 DecodeNesting_CheckBoundedType() is always called before this and
3148 makes sure pCurrentBounded is valid.
3149 */
3150 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3151
3152 /*
3153 This does the complex work of leveling up the pre-order traversal
3154 when the end of a map or array or another bounded level is
3155 reached. It may do nothing, or ascend all the way to the top
3156 level.
3157 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003158 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003159 if(uErr != QCBOR_SUCCESS) {
3160 goto Done;
3161 }
3162
Laurence Lundblade02625d42020-06-25 14:41:41 -07003163 /*
3164 This makes the next highest bounded level the current bounded
3165 level. If there is no next highest level, then no bounded mode is
3166 in effect.
3167 */
3168 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003169
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003170 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003171
3172Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003173 return uErr;
3174}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003175
Laurence Lundblade02625d42020-06-25 14:41:41 -07003176
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003177// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003178void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003179{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003180 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003181 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003182 return;
3183 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003184
Laurence Lundblade02625d42020-06-25 14:41:41 -07003185 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003186
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003187 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003188 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003189 goto Done;
3190 }
3191
Laurence Lundblade02625d42020-06-25 14:41:41 -07003192 /*
3193 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003194 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003195 from previous map search, then do a dummy search.
3196 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003197 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003198 QCBORItem Dummy;
3199 Dummy.uLabelType = QCBOR_TYPE_NONE;
3200 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3201 if(uErr != QCBOR_SUCCESS) {
3202 goto Done;
3203 }
3204 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003205
Laurence Lundblade02625d42020-06-25 14:41:41 -07003206 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003207
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003208Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003209 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003210}
3211
3212
Laurence Lundblade1341c592020-04-11 14:19:05 -07003213
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003214static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003215 const QCBORItem *pItem,
3216 uint8_t uTagRequirement,
3217 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003218{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003219 if(pBstr) {
3220 *pBstr = NULLUsefulBufC;
3221 }
3222
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003223 if(pMe->uLastError != QCBOR_SUCCESS) {
3224 // Already in error state; do nothing.
3225 return pMe->uLastError;
3226 }
3227
3228 QCBORError uError = QCBOR_SUCCESS;
3229
3230 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3231 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3232 goto Done;;
3233 }
3234
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003235 const TagSpecification TagSpec =
3236 {
3237 uTagRequirement,
3238 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3239 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3240 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003241
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003242 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003243 if(uError != QCBOR_SUCCESS) {
3244 goto Done;
3245 }
3246
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003247 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003248 // Reverse the decrement done by GetNext() for the bstr so the
3249 // increment in NestLevelAscender() called by ExitBoundedLevel()
3250 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003251 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003252 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003253
3254 if(pBstr) {
3255 *pBstr = pItem->val.string;
3256 }
3257
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003258 // This saves the current length of the UsefulInputBuf and then
3259 // narrows the UsefulInputBuf to start and length of the wrapped
3260 // CBOR that is being entered.
3261 //
3262 // This makes sure the length is less than
3263 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3264 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3265 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3266 // the casts safe. uEndOfBstr will always be less than
3267 // uPreviousLength because of the way UsefulInputBuf works so there
3268 // is no need to check it. There is also a range check in the
3269 // seek.
3270 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003271 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003272 // amount to much code.
3273 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3274 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003275 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003276 goto Done;
3277 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003278 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003279 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003280 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003281
Laurence Lundblade02625d42020-06-25 14:41:41 -07003282 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003283 (uint32_t)uPreviousLength,
3284 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003285Done:
3286 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003287}
3288
3289
Laurence Lundblade02625d42020-06-25 14:41:41 -07003290/*
3291 Public function, see header qcbor/qcbor_decode.h file
3292 */
3293void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003294 uint8_t uTagRequirement,
3295 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003296{
3297 if(pMe->uLastError != QCBOR_SUCCESS) {
3298 // Already in error state; do nothing.
3299 return;
3300 }
3301
3302 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003303 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003304 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3305 if(pMe->uLastError != QCBOR_SUCCESS) {
3306 return;
3307 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003308
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003309 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003310 &Item,
3311 uTagRequirement,
3312 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003313}
3314
3315
Laurence Lundblade02625d42020-06-25 14:41:41 -07003316/*
3317 Public function, see header qcbor/qcbor_decode.h file
3318 */
3319void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003320 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003321 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003322 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003323{
3324 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003325 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003326
Laurence Lundblade93d89472020-10-03 22:30:50 -07003327 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3328 &Item,
3329 uTagRequirement,
3330 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003331}
3332
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003333
Laurence Lundblade02625d42020-06-25 14:41:41 -07003334/*
3335 Public function, see header qcbor/qcbor_decode.h file
3336 */
3337void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003338 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003339 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003340 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003341{
3342 QCBORItem Item;
3343 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3344
Laurence Lundblade93d89472020-10-03 22:30:50 -07003345 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3346 &Item,
3347 uTagRequirement,
3348 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003349}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003350
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003351
Laurence Lundblade02625d42020-06-25 14:41:41 -07003352/*
3353 Public function, see header qcbor/qcbor_decode.h file
3354 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003355void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003356{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003357 if(pMe->uLastError != QCBOR_SUCCESS) {
3358 // Already in error state; do nothing.
3359 return;
3360 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003361
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003362 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003363 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003364 return;
3365 }
3366
3367 /*
3368 Reset the length of the UsefulInputBuf to what it was before
3369 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003370 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003371 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003372 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003373
3374
Laurence Lundblade02625d42020-06-25 14:41:41 -07003375 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003376 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003377}
3378
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003379
Laurence Lundbladee6430642020-03-14 21:15:44 -07003380
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003381
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003382
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003383
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003384
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003385
Laurence Lundblade93d89472020-10-03 22:30:50 -07003386static QCBORError
3387InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003388{
3389 switch(pItem->uDataType) {
3390 case QCBOR_TYPE_TRUE:
3391 *pBool = true;
3392 return QCBOR_SUCCESS;
3393 break;
3394
3395 case QCBOR_TYPE_FALSE:
3396 *pBool = false;
3397 return QCBOR_SUCCESS;
3398 break;
3399
3400 default:
3401 return QCBOR_ERR_UNEXPECTED_TYPE;
3402 break;
3403 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003404 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003405}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003406
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003407
Laurence Lundblade9b334962020-08-27 10:55:53 -07003408
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003409/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003410 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003411*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003412void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003413{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003414 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003415 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003416 return;
3417 }
3418
Laurence Lundbladec4537442020-04-14 18:53:22 -07003419 QCBORError nError;
3420 QCBORItem Item;
3421
3422 nError = QCBORDecode_GetNext(pMe, &Item);
3423 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003424 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003425 return;
3426 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003427 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003428}
3429
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003430
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003431/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003432 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003433*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003434void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003435{
3436 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003437 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003438
Laurence Lundblade9b334962020-08-27 10:55:53 -07003439 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003440}
3441
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003442
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003443/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003444 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003445*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003446void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3447{
3448 QCBORItem Item;
3449 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3450
Laurence Lundblade9b334962020-08-27 10:55:53 -07003451 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003452}
3453
3454
3455
Laurence Lundbladec7114722020-08-13 05:11:40 -07003456
3457static void ProcessEpochDate(QCBORDecodeContext *pMe,
3458 QCBORItem *pItem,
3459 uint8_t uTagRequirement,
3460 int64_t *pnTime)
3461{
3462 if(pMe->uLastError != QCBOR_SUCCESS) {
3463 // Already in error state, do nothing
3464 return;
3465 }
3466
3467 QCBORError uErr;
3468
3469 const TagSpecification TagSpec =
3470 {
3471 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003472 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3473 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003474 };
3475
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003476 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003477 if(uErr != QCBOR_SUCCESS) {
3478 goto Done;
3479 }
3480
3481 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3482 uErr = DecodeDateEpoch(pItem);
3483 if(uErr != QCBOR_SUCCESS) {
3484 goto Done;
3485 }
3486 }
3487
Laurence Lundblade9b334962020-08-27 10:55:53 -07003488 // Save the tags in the last item's tags in the decode context
3489 // for QCBORDecode_GetNthTagOfLast()
3490 CopyTags(pMe, pItem);
3491
Laurence Lundbladec7114722020-08-13 05:11:40 -07003492 *pnTime = pItem->val.epochDate.nSeconds;
3493
3494Done:
3495 pMe->uLastError = (uint8_t)uErr;
3496}
3497
3498
3499void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003500 uint8_t uTagRequirement,
3501 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003502{
3503 if(pMe->uLastError != QCBOR_SUCCESS) {
3504 // Already in error state, do nothing
3505 return;
3506 }
3507
3508 QCBORItem Item;
3509 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3510
3511 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3512}
3513
3514
3515void
3516QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3517 int64_t nLabel,
3518 uint8_t uTagRequirement,
3519 int64_t *pnTime)
3520{
3521 QCBORItem Item;
3522 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3523 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3524}
3525
3526
3527void
3528QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3529 const char *szLabel,
3530 uint8_t uTagRequirement,
3531 int64_t *pnTime)
3532{
3533 QCBORItem Item;
3534 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3535 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3536}
3537
3538
3539
3540
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003541void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3542 TagSpecification TagSpec,
3543 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003544{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003545 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003546 // Already in error state, do nothing
3547 return;
3548 }
3549
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003550 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003551 QCBORItem Item;
3552
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003553 uError = QCBORDecode_GetNext(pMe, &Item);
3554 if(uError != QCBOR_SUCCESS) {
3555 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003556 return;
3557 }
3558
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003559 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003560
3561 if(pMe->uLastError == QCBOR_SUCCESS) {
3562 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003563 } else {
3564 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003565 }
3566}
3567
Laurence Lundbladec4537442020-04-14 18:53:22 -07003568
3569
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003570
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003571static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003572 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003573 UsefulBufC *pValue,
3574 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003575{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003576 const TagSpecification TagSpec =
3577 {
3578 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003579 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3580 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003581 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003582
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003583 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003584 if(uErr != QCBOR_SUCCESS) {
3585 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003586 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003587
3588 *pValue = pItem->val.string;
3589
3590 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3591 *pbIsNegative = false;
3592 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3593 *pbIsNegative = true;
3594 }
3595
3596 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003597}
3598
3599
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003600/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003601 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003602 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003603void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3604 uint8_t uTagRequirement,
3605 UsefulBufC *pValue,
3606 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003607{
3608 if(pMe->uLastError != QCBOR_SUCCESS) {
3609 // Already in error state, do nothing
3610 return;
3611 }
3612
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003613 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003614 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3615 if(uError != QCBOR_SUCCESS) {
3616 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003617 return;
3618 }
3619
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003620 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003621}
3622
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003623
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003624/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003625 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003626*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003627void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3628 int64_t nLabel,
3629 uint8_t uTagRequirement,
3630 UsefulBufC *pValue,
3631 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003632{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003633 QCBORItem Item;
3634 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003635 if(pMe->uLastError != QCBOR_SUCCESS) {
3636 return;
3637 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003638
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003639 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003640}
3641
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003642
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003643/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003644 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003645*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003646void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3647 const char *szLabel,
3648 uint8_t uTagRequirement,
3649 UsefulBufC *pValue,
3650 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003651{
3652 QCBORItem Item;
3653 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003654 if(pMe->uLastError != QCBOR_SUCCESS) {
3655 return;
3656 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003657
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003658 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003659}
3660
3661
3662
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003663
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003664// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003665QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3666 const QCBORItem *pItem,
3667 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003668 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003669{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003670 const TagSpecification TagSpecText =
3671 {
3672 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003673 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3674 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003675 };
3676 const TagSpecification TagSpecBinary =
3677 {
3678 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003679 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3680 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003681 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003682
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003683 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003684
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003685 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003686 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003687 if(pbIsTag257 != NULL) {
3688 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003689 }
3690 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003691 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003692 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003693 if(pbIsTag257 != NULL) {
3694 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003695 }
3696 uReturn = QCBOR_SUCCESS;
3697
3698 } else {
3699 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3700 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003701
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003702 return uReturn;
3703}
3704
Laurence Lundblade93d89472020-10-03 22:30:50 -07003705// Improvement: add methods for wrapped CBOR, a simple alternate
3706// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003707
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003708
3709
3710
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003711#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003712
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003713typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003714
3715
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003716// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003717static QCBORError
3718Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003719{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003720 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003721
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003722 if(uResult != 0) {
3723 /* This loop will run a maximum of 19 times because
3724 * UINT64_MAX < 10 ^^ 19. More than that will cause
3725 * exit with the overflow error
3726 */
3727 for(; nExponent > 0; nExponent--) {
3728 if(uResult > UINT64_MAX / 10) {
3729 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3730 }
3731 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003732 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003733
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003734 for(; nExponent < 0; nExponent++) {
3735 uResult = uResult / 10;
3736 if(uResult == 0) {
3737 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3738 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003739 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003740 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003741 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003742
3743 *puResult = uResult;
3744
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003745 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003746}
3747
3748
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003749// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003750static QCBORError
3751Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003752{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003753 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003754
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003755 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003756
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003757 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003758 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003759 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003760 */
3761 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003762 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003763 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003764 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003765 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003766 nExponent--;
3767 }
3768
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003769 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003770 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003771 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3772 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003773 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003774 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003775 }
3776
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003777 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003778
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003779 return QCBOR_SUCCESS;
3780}
3781
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003782
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003783/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003784 Compute value with signed mantissa and signed result. Works with
3785 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003786 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003787static inline QCBORError ExponentiateNN(int64_t nMantissa,
3788 int64_t nExponent,
3789 int64_t *pnResult,
3790 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003791{
3792 uint64_t uResult;
3793
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003794 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003795 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003796 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3797
3798 // Do the exponentiation of the positive mantissa
3799 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3800 if(uReturn) {
3801 return uReturn;
3802 }
3803
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003804
Laurence Lundblade983500d2020-05-14 11:49:34 -07003805 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3806 of INT64_MIN. This assumes two's compliment representation where
3807 INT64_MIN is one increment farther from 0 than INT64_MAX.
3808 Trying to write -INT64_MIN doesn't work to get this because the
3809 compiler tries to work with an int64_t which can't represent
3810 -INT64_MIN.
3811 */
3812 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3813
3814 // Error out if too large
3815 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003816 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3817 }
3818
3819 // Casts are safe because of checks above
3820 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3821
3822 return QCBOR_SUCCESS;
3823}
3824
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003825
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003826/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003827 Compute value with signed mantissa and unsigned result. Works with
3828 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003829 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003830static inline QCBORError ExponentitateNU(int64_t nMantissa,
3831 int64_t nExponent,
3832 uint64_t *puResult,
3833 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003834{
3835 if(nMantissa < 0) {
3836 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3837 }
3838
3839 // Cast to unsigned is OK because of check for negative
3840 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3841 // Exponentiation is straight forward
3842 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3843}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003844
3845
3846/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003847 Compute value with signed mantissa and unsigned result. Works with
3848 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003849 */
3850static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3851 int64_t nExponent,
3852 uint64_t *puResult,
3853 fExponentiator pfExp)
3854{
3855 return (*pfExp)(uMantissa, nExponent, puResult);
3856}
3857
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003858#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3859
3860
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003861
3862
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003863
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003864static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003865{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003866 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003867
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003868 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003869 const uint8_t *pByte = BigNum.ptr;
3870 size_t uLen = BigNum.len;
3871 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003872 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003873 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003874 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003875 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003876 }
3877
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003878 *pResult = uResult;
3879 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003880}
3881
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003882
Laurence Lundblade887add82020-05-17 05:50:34 -07003883static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003884{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003885 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003886}
3887
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003888
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003889static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003890{
3891 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003892 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3893 if(uError) {
3894 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003895 }
3896 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3897 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003898 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003899}
3900
3901
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003902static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003903{
3904 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003905 /* The negative integer furthest from zero for a C int64_t is
3906 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3907 negative number in CBOR is computed as -n - 1 where n is the
3908 encoded integer, where n is what is in the variable BigNum. When
3909 converting BigNum to a uint64_t, the maximum value is thus
3910 INT64_MAX, so that when it -n - 1 is applied to it the result will
3911 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003912
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003913 -n - 1 <= INT64_MIN.
3914 -n - 1 <= -INT64_MAX - 1
3915 n <= INT64_MAX.
3916 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003917 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003918 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003919 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003920 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003921
3922 /// Now apply -n - 1. The cast is safe because
3923 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3924 // is the largest positive integer that an int64_t can
3925 // represent. */
3926 *pnResult = -(int64_t)uResult - 1;
3927
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003928 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003929}
3930
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003931
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003932
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003933
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003934
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003935/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003936Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003937
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003938\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003939
Laurence Lundblade93d89472020-10-03 22:30:50 -07003940\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
3941 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003942
3943\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3944
Laurence Lundblade93d89472020-10-03 22:30:50 -07003945\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
3946 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003947*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07003948static QCBORError
3949ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003950{
3951 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003952 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003953 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003954#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003955 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003956 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3957 http://www.cplusplus.com/reference/cmath/llround/
3958 */
3959 // Not interested in FE_INEXACT
3960 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003961 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3962 *pnValue = llround(pItem->val.dfnum);
3963 } else {
3964 *pnValue = lroundf(pItem->val.fnum);
3965 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003966 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
3967 // llround() shouldn't result in divide by zero, but catch
3968 // it here in case it unexpectedly does. Don't try to
3969 // distinguish between the various exceptions because it seems
3970 // they vary by CPU, compiler and OS.
3971 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003972 }
3973 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003974 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003975 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003976#else
3977 return QCBOR_ERR_HW_FLOAT_DISABLED;
3978#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003979 break;
3980
3981 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003982 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003983 *pnValue = pItem->val.int64;
3984 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003985 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003986 }
3987 break;
3988
3989 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003990 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003991 if(pItem->val.uint64 < INT64_MAX) {
3992 *pnValue = pItem->val.int64;
3993 } else {
3994 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3995 }
3996 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003997 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003998 }
3999 break;
4000
4001 default:
4002 return QCBOR_ERR_UNEXPECTED_TYPE;
4003 }
4004 return QCBOR_SUCCESS;
4005}
4006
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004007
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004008void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004009 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004010 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004011 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004012{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004013 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004014 return;
4015 }
4016
Laurence Lundbladee6430642020-03-14 21:15:44 -07004017 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004018 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4019 if(uError) {
4020 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004021 return;
4022 }
4023
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004024 if(pItem) {
4025 *pItem = Item;
4026 }
4027
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004028 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004029}
4030
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004031
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004032void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4033 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004034 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004035 int64_t *pnValue,
4036 QCBORItem *pItem)
4037{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004038 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004039 if(pMe->uLastError != QCBOR_SUCCESS) {
4040 return;
4041 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004042
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004043 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004044}
4045
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004046
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004047void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4048 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004049 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004050 int64_t *pnValue,
4051 QCBORItem *pItem)
4052{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004053 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004054 if(pMe->uLastError != QCBOR_SUCCESS) {
4055 return;
4056 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004057
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004058 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004059}
4060
4061
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004062/*
4063 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004064
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004065 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004066
Laurence Lundblade93d89472020-10-03 22:30:50 -07004067 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4068 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004069
4070 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4071
Laurence Lundblade93d89472020-10-03 22:30:50 -07004072 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4073 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004074 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004075static QCBORError
4076Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004077{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004078 switch(pItem->uDataType) {
4079
4080 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004081 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004082 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004083 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004084 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004085 }
4086 break;
4087
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004088 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004089 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004090 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004091 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004092 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004093 }
4094 break;
4095
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004096#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4097 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004098 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004099 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004100 pItem->val.expAndMantissa.nExponent,
4101 pnValue,
4102 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004103 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004104 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004105 }
4106 break;
4107
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004108 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004109 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004110 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004111 pItem->val.expAndMantissa.nExponent,
4112 pnValue,
4113 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004114 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004115 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004116 }
4117 break;
4118
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004119 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004120 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004121 int64_t nMantissa;
4122 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004123 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4124 if(uErr) {
4125 return uErr;
4126 }
4127 return ExponentiateNN(nMantissa,
4128 pItem->val.expAndMantissa.nExponent,
4129 pnValue,
4130 Exponentitate10);
4131 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004132 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004133 }
4134 break;
4135
4136 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004137 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004138 int64_t nMantissa;
4139 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004140 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4141 if(uErr) {
4142 return uErr;
4143 }
4144 return ExponentiateNN(nMantissa,
4145 pItem->val.expAndMantissa.nExponent,
4146 pnValue,
4147 Exponentitate10);
4148 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004149 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004150 }
4151 break;
4152
4153 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004154 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004155 int64_t nMantissa;
4156 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004157 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4158 if(uErr) {
4159 return uErr;
4160 }
4161 return ExponentiateNN(nMantissa,
4162 pItem->val.expAndMantissa.nExponent,
4163 pnValue,
4164 Exponentitate2);
4165 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004166 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004167 }
4168 break;
4169
4170 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004171 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004172 int64_t nMantissa;
4173 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004174 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4175 if(uErr) {
4176 return uErr;
4177 }
4178 return ExponentiateNN(nMantissa,
4179 pItem->val.expAndMantissa.nExponent,
4180 pnValue,
4181 Exponentitate2);
4182 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004183 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004184 }
4185 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004186#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4187
Laurence Lundbladee6430642020-03-14 21:15:44 -07004188
Laurence Lundbladec4537442020-04-14 18:53:22 -07004189 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004190 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004191}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004192
4193
Laurence Lundbladec4537442020-04-14 18:53:22 -07004194/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004195 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004196 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004197void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004198{
4199 QCBORItem Item;
4200
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004201 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004202
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004203 if(pMe->uLastError == QCBOR_SUCCESS) {
4204 // The above conversion succeeded
4205 return;
4206 }
4207
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004208 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004209 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004210 return;
4211 }
4212
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004213 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004214}
4215
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004216
4217/*
4218Public function, see header qcbor/qcbor_decode.h file
4219*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004220void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4221 int64_t nLabel,
4222 uint32_t uConvertTypes,
4223 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004224{
4225 QCBORItem Item;
4226
Laurence Lundblade93d89472020-10-03 22:30:50 -07004227 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4228 nLabel,
4229 uConvertTypes,
4230 pnValue,
4231 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004232
4233 if(pMe->uLastError == QCBOR_SUCCESS) {
4234 // The above conversion succeeded
4235 return;
4236 }
4237
4238 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4239 // The above conversion failed in a way that code below can't correct
4240 return;
4241 }
4242
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004243 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004244}
4245
4246
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004247/*
4248Public function, see header qcbor/qcbor_decode.h file
4249*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004250void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4251 const char *szLabel,
4252 uint32_t uConvertTypes,
4253 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004254{
4255 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004256 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4257 szLabel,
4258 uConvertTypes,
4259 pnValue,
4260 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004261
4262 if(pMe->uLastError == QCBOR_SUCCESS) {
4263 // The above conversion succeeded
4264 return;
4265 }
4266
4267 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4268 // The above conversion failed in a way that code below can't correct
4269 return;
4270 }
4271
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004272 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004273}
4274
4275
Laurence Lundblade93d89472020-10-03 22:30:50 -07004276static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004277{
4278 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004279 case QCBOR_TYPE_DOUBLE:
4280 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004281#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004282 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004283 // Can't use llround here because it will not convert values
4284 // greater than INT64_MAX and less than UINT64_MAX that
4285 // need to be converted so it is more complicated.
4286 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4287 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4288 if(isnan(pItem->val.dfnum)) {
4289 return QCBOR_ERR_FLOAT_EXCEPTION;
4290 } else if(pItem->val.dfnum < 0) {
4291 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4292 } else {
4293 double dRounded = round(pItem->val.dfnum);
4294 // See discussion in DecodeDateEpoch() for
4295 // explanation of - 0x7ff
4296 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4297 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4298 }
4299 *puValue = (uint64_t)dRounded;
4300 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004301 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004302 if(isnan(pItem->val.fnum)) {
4303 return QCBOR_ERR_FLOAT_EXCEPTION;
4304 } else if(pItem->val.fnum < 0) {
4305 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4306 } else {
4307 float fRounded = roundf(pItem->val.fnum);
4308 // See discussion in DecodeDateEpoch() for
4309 // explanation of - 0x7ff
4310 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4311 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4312 }
4313 *puValue = (uint64_t)fRounded;
4314 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004315 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004316 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4317 // round() and roundf() shouldn't result in exceptions here, but
4318 // catch them to be robust and thorough. Don't try to
4319 // distinguish between the various exceptions because it seems
4320 // they vary by CPU, compiler and OS.
4321 return QCBOR_ERR_FLOAT_EXCEPTION;
4322 }
4323
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004324 } else {
4325 return QCBOR_ERR_UNEXPECTED_TYPE;
4326 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004327#else
4328 return QCBOR_ERR_HW_FLOAT_DISABLED;
4329#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004330 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004331
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004332 case QCBOR_TYPE_INT64:
4333 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4334 if(pItem->val.int64 >= 0) {
4335 *puValue = (uint64_t)pItem->val.int64;
4336 } else {
4337 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4338 }
4339 } else {
4340 return QCBOR_ERR_UNEXPECTED_TYPE;
4341 }
4342 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004343
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004344 case QCBOR_TYPE_UINT64:
4345 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4346 *puValue = pItem->val.uint64;
4347 } else {
4348 return QCBOR_ERR_UNEXPECTED_TYPE;
4349 }
4350 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004351
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004352 default:
4353 return QCBOR_ERR_UNEXPECTED_TYPE;
4354 }
4355
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004356 return QCBOR_SUCCESS;
4357}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004358
4359
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004360void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004361 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004362 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004363 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004364{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004365 if(pMe->uLastError != QCBOR_SUCCESS) {
4366 return;
4367 }
4368
Laurence Lundbladec4537442020-04-14 18:53:22 -07004369 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004370
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004371 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4372 if(uError) {
4373 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004374 return;
4375 }
4376
Laurence Lundbladea826c502020-05-10 21:07:00 -07004377 if(pItem) {
4378 *pItem = Item;
4379 }
4380
Laurence Lundblade93d89472020-10-03 22:30:50 -07004381 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004382}
4383
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004384
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004385void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004386 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004387 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004388 uint64_t *puValue,
4389 QCBORItem *pItem)
4390{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004391 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004392 if(pMe->uLastError != QCBOR_SUCCESS) {
4393 return;
4394 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004395
Laurence Lundblade93d89472020-10-03 22:30:50 -07004396 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004397}
4398
4399
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004400void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004401 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004402 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004403 uint64_t *puValue,
4404 QCBORItem *pItem)
4405{
4406 if(pMe->uLastError != QCBOR_SUCCESS) {
4407 return;
4408 }
4409
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004410 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004411 if(pMe->uLastError != QCBOR_SUCCESS) {
4412 return;
4413 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004414
Laurence Lundblade93d89472020-10-03 22:30:50 -07004415 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004416}
4417
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004418
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004419
Laurence Lundblade93d89472020-10-03 22:30:50 -07004420static QCBORError
4421UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004422{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004423 switch(pItem->uDataType) {
4424
4425 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004426 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004427 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4428 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004429 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004430 }
4431 break;
4432
4433 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004434 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004435 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4436 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004437 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004438 }
4439 break;
4440
4441#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4442
4443 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004444 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004445 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004446 pItem->val.expAndMantissa.nExponent,
4447 puValue,
4448 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004449 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004450 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004451 }
4452 break;
4453
4454 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004455 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004456 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4457 pItem->val.expAndMantissa.nExponent,
4458 puValue,
4459 Exponentitate2);
4460 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004461 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004462 }
4463 break;
4464
4465 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004466 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004467 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004468 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004469 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004470 if(uErr != QCBOR_SUCCESS) {
4471 return uErr;
4472 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004473 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004474 pItem->val.expAndMantissa.nExponent,
4475 puValue,
4476 Exponentitate10);
4477 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004478 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004479 }
4480 break;
4481
4482 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004483 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004484 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4485 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004486 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004487 }
4488 break;
4489
4490 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004491 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004492 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004493 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004494 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004495 if(uErr != QCBOR_SUCCESS) {
4496 return uErr;
4497 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004498 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004499 pItem->val.expAndMantissa.nExponent,
4500 puValue,
4501 Exponentitate2);
4502 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004503 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004504 }
4505 break;
4506
4507 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004508 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004509 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4510 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004511 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004512 }
4513 break;
4514#endif
4515 default:
4516 return QCBOR_ERR_UNEXPECTED_TYPE;
4517 }
4518}
4519
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004520
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004521/*
4522 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004523 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004524void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004525{
4526 QCBORItem Item;
4527
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004528 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004529
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004530 if(pMe->uLastError == QCBOR_SUCCESS) {
4531 // The above conversion succeeded
4532 return;
4533 }
4534
4535 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4536 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004537 return;
4538 }
4539
Laurence Lundblade93d89472020-10-03 22:30:50 -07004540 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004541}
4542
Laurence Lundbladec4537442020-04-14 18:53:22 -07004543
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004544/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004545 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004546*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004547void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004548 int64_t nLabel,
4549 uint32_t uConvertTypes,
4550 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004551{
4552 QCBORItem Item;
4553
Laurence Lundblade93d89472020-10-03 22:30:50 -07004554 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4555 nLabel,
4556 uConvertTypes,
4557 puValue,
4558 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004559
4560 if(pMe->uLastError == QCBOR_SUCCESS) {
4561 // The above conversion succeeded
4562 return;
4563 }
4564
4565 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4566 // The above conversion failed in a way that code below can't correct
4567 return;
4568 }
4569
Laurence Lundblade93d89472020-10-03 22:30:50 -07004570 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004571}
4572
4573
4574/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004575 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004576*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004577void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004578 const char *szLabel,
4579 uint32_t uConvertTypes,
4580 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004581{
4582 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004583 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4584 szLabel,
4585 uConvertTypes,
4586 puValue,
4587 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004588
4589 if(pMe->uLastError == QCBOR_SUCCESS) {
4590 // The above conversion succeeded
4591 return;
4592 }
4593
4594 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4595 // The above conversion failed in a way that code below can't correct
4596 return;
4597 }
4598
Laurence Lundblade93d89472020-10-03 22:30:50 -07004599 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004600}
4601
4602
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004603
4604
Laurence Lundblade9b334962020-08-27 10:55:53 -07004605static QCBORError ConvertDouble(const QCBORItem *pItem,
4606 uint32_t uConvertTypes,
4607 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004608{
4609 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004610 case QCBOR_TYPE_FLOAT:
4611#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4612 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4613 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004614 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004615 *pdValue = (double)pItem->val.fnum;
4616 } else {
4617 return QCBOR_ERR_UNEXPECTED_TYPE;
4618 }
4619 }
4620#else
4621 return QCBOR_ERR_HW_FLOAT_DISABLED;
4622#endif
4623 break;
4624
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004625 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004626 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4627 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004628 *pdValue = pItem->val.dfnum;
4629 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004630 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004631 }
4632 }
4633 break;
4634
4635 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004636#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004637 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004638 // A simple cast seems to do the job with no worry of exceptions.
4639 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004640 *pdValue = (double)pItem->val.int64;
4641
4642 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004643 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004644 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004645#else
4646 return QCBOR_ERR_HW_FLOAT_DISABLED;
4647#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004648 break;
4649
4650 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004651#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004652 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004653 // A simple cast seems to do the job with no worry of exceptions.
4654 // There will be precision loss for some values.
4655 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004656 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004657 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004658 }
4659 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004660#else
4661 return QCBOR_ERR_HW_FLOAT_DISABLED;
4662#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004663
4664 default:
4665 return QCBOR_ERR_UNEXPECTED_TYPE;
4666 }
4667
4668 return QCBOR_SUCCESS;
4669}
4670
4671
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004672void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004673 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004674 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004675 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004676{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004677 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004678 return;
4679 }
4680
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004681 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004682
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004683 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004684 if(uError) {
4685 pMe->uLastError = (uint8_t)uError;
4686 return;
4687 }
4688
4689 if(pItem) {
4690 *pItem = Item;
4691 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004692
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004693 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004694}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004695
Laurence Lundbladec4537442020-04-14 18:53:22 -07004696
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004697void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4698 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004699 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004700 double *pdValue,
4701 QCBORItem *pItem)
4702{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004703 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004704 if(pMe->uLastError != QCBOR_SUCCESS) {
4705 return;
4706 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004707
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004708 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004709}
4710
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004711
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004712void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4713 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004714 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004715 double *pdValue,
4716 QCBORItem *pItem)
4717{
4718 if(pMe->uLastError != QCBOR_SUCCESS) {
4719 return;
4720 }
4721
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004722 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004723 if(pMe->uLastError != QCBOR_SUCCESS) {
4724 return;
4725 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004726
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004727 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004728}
4729
4730
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004731#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004732static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4733{
4734 double dResult;
4735
4736 dResult = 0.0;
4737 const uint8_t *pByte = BigNum.ptr;
4738 size_t uLen = BigNum.len;
4739 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004740 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004741 while(uLen--) {
4742 dResult = (dResult * 256.0) + (double)*pByte++;
4743 }
4744
4745 return dResult;
4746}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004747#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4748
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004749
Laurence Lundblade93d89472020-10-03 22:30:50 -07004750static QCBORError
4751DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004752{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004753#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004754 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004755 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4756
4757 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004758 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004759
4760#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004761 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004762 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004763 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004764 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4765 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4766 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004767 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004768 }
4769 break;
4770
4771 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004772 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004773 // Underflow gives 0, overflow gives infinity
4774 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4775 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004776 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004777 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004778 }
4779 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004780#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004781
4782 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004783 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004784 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4785 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004786 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004787 }
4788 break;
4789
4790 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004791 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004792 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004793 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004794 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004795 }
4796 break;
4797
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004798#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004799 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004800 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004801 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4802 *pdValue = dMantissa * pow(10, (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_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004809 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004810 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4811 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4812 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004813 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004814 }
4815 break;
4816
4817 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004818 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004819 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4820 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4821 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004822 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004823 }
4824 break;
4825
4826 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004827 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004828 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004829 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4830 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004831 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004832 }
4833 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004834#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4835
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004836 default:
4837 return QCBOR_ERR_UNEXPECTED_TYPE;
4838 }
4839
4840 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004841
4842#else
4843 (void)pItem;
4844 (void)uConvertTypes;
4845 (void)pdValue;
4846 return QCBOR_ERR_HW_FLOAT_DISABLED;
4847#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4848
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004849}
4850
4851
4852/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004853 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004854*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004855void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4856 uint32_t uConvertTypes,
4857 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004858{
4859
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004860 QCBORItem Item;
4861
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004862 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004863
4864 if(pMe->uLastError == QCBOR_SUCCESS) {
4865 // The above conversion succeeded
4866 return;
4867 }
4868
4869 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4870 // The above conversion failed in a way that code below can't correct
4871 return;
4872 }
4873
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004874 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004875}
4876
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004877
4878/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004879 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004880*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004881void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4882 int64_t nLabel,
4883 uint32_t uConvertTypes,
4884 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004885{
4886 QCBORItem Item;
4887
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004888 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004889
4890 if(pMe->uLastError == QCBOR_SUCCESS) {
4891 // The above conversion succeeded
4892 return;
4893 }
4894
4895 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4896 // The above conversion failed in a way that code below can't correct
4897 return;
4898 }
4899
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004900 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004901}
4902
4903
4904/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004905 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004906*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004907void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4908 const char *szLabel,
4909 uint32_t uConvertTypes,
4910 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004911{
4912 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004913 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004914
4915 if(pMe->uLastError == QCBOR_SUCCESS) {
4916 // The above conversion succeeded
4917 return;
4918 }
4919
4920 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4921 // The above conversion failed in a way that code below can't correct
4922 return;
4923 }
4924
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004925 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004926}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004927
4928
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004929
4930
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004931#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004932static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4933{
4934 while((uInt & 0xff00000000000000UL) == 0) {
4935 uInt = uInt << 8;
4936 };
4937
4938 UsefulOutBuf UOB;
4939
4940 UsefulOutBuf_Init(&UOB, Buffer);
4941
4942 while(uInt) {
4943 const uint64_t xx = uInt & 0xff00000000000000UL;
4944 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4945 uInt = uInt << 8;
4946 (void)xx;
4947 }
4948
4949 return UsefulOutBuf_OutUBuf(&UOB);
4950}
4951
4952
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004953static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4954 TagSpecification TagSpec,
4955 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004956{
4957 QCBORError uErr;
4958 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004959 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004960 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004961 if(uErr != QCBOR_SUCCESS) {
4962 goto Done;
4963 }
4964
4965 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4966 break; // Successful exit. Moving on to finish decoding.
4967 }
4968
4969 // The item is an array, which means an undecoded
4970 // mantissa and exponent, so decode it. It will then
4971 // have a different type and exit the loop if.
4972 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4973 if(uErr != QCBOR_SUCCESS) {
4974 goto Done;
4975 }
4976
4977 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07004978 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004979 }
4980Done:
4981 return uErr;
4982}
4983
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004984
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004985static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004986 TagSpecification TagSpec,
4987 QCBORItem *pItem,
4988 int64_t *pnMantissa,
4989 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004990{
4991 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004992
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004993 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004994 if(uErr != QCBOR_SUCCESS) {
4995 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004996 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004997
Laurence Lundblade9b334962020-08-27 10:55:53 -07004998 switch (pItem->uDataType) {
4999
5000 case QCBOR_TYPE_DECIMAL_FRACTION:
5001 case QCBOR_TYPE_BIGFLOAT:
5002 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5003 *pnExponent = pItem->val.expAndMantissa.nExponent;
5004 break;
5005
5006 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5007 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5008 *pnExponent = pItem->val.expAndMantissa.nExponent;
5009 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5010 break;
5011
5012 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5013 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5014 *pnExponent = pItem->val.expAndMantissa.nExponent;
5015 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5016 break;
5017
5018 default:
5019 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5020 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005021
5022 Done:
5023 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005024}
5025
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005026
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005027static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005028 TagSpecification TagSpec,
5029 QCBORItem *pItem,
5030 UsefulBuf BufferForMantissa,
5031 UsefulBufC *pMantissa,
5032 bool *pbIsNegative,
5033 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005034{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005035 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005036
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005037 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005038 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005039 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005040 }
5041
5042 uint64_t uMantissa;
5043
5044 switch (pItem->uDataType) {
5045
5046 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005047 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005048 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5049 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5050 *pbIsNegative = false;
5051 } else {
5052 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5053 *pbIsNegative = true;
5054 }
5055 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5056 *pnExponent = pItem->val.expAndMantissa.nExponent;
5057 break;
5058
5059 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005060 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005061 *pnExponent = pItem->val.expAndMantissa.nExponent;
5062 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5063 *pbIsNegative = false;
5064 break;
5065
5066 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005067 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005068 *pnExponent = pItem->val.expAndMantissa.nExponent;
5069 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5070 *pbIsNegative = true;
5071 break;
5072
5073 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005074 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005075 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005076
5077Done:
5078 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005079}
5080
5081
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005082/*
5083 Public function, see header qcbor/qcbor_decode.h file
5084*/
5085void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5086 uint8_t uTagRequirement,
5087 int64_t *pnMantissa,
5088 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005089{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005090 if(pMe->uLastError != QCBOR_SUCCESS) {
5091 return;
5092 }
5093
5094 QCBORItem Item;
5095 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5096 if(uError) {
5097 pMe->uLastError = (uint8_t)uError;
5098 return;
5099 }
5100
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005101 const TagSpecification TagSpec =
5102 {
5103 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005104 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5105 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5106 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005107 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005108
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005109 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005110}
5111
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005112
5113/*
5114 Public function, see header qcbor/qcbor_decode.h file
5115*/
5116void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005117 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005118 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005119 int64_t *pnMantissa,
5120 int64_t *pnExponent)
5121{
5122 if(pMe->uLastError != QCBOR_SUCCESS) {
5123 return;
5124 }
5125
5126 QCBORItem Item;
5127 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5128
5129 const TagSpecification TagSpec =
5130 {
5131 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005132 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5133 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5134 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005135 };
5136
5137 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5138}
5139
5140
5141/*
5142 Public function, see header qcbor/qcbor_decode.h file
5143*/
5144void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005145 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005146 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005147 int64_t *pnMantissa,
5148 int64_t *pnExponent)
5149{
5150 if(pMe->uLastError != QCBOR_SUCCESS) {
5151 return;
5152 }
5153
5154 QCBORItem Item;
5155 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5156
5157 const TagSpecification TagSpec =
5158 {
5159 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005160 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5161 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5162 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005163 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005164
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005165 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5166}
5167
5168
5169/*
5170 Public function, see header qcbor/qcbor_decode.h file
5171*/
5172void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5173 uint8_t uTagRequirement,
5174 UsefulBuf MantissaBuffer,
5175 UsefulBufC *pMantissa,
5176 bool *pbMantissaIsNegative,
5177 int64_t *pnExponent)
5178{
5179 if(pMe->uLastError != QCBOR_SUCCESS) {
5180 return;
5181 }
5182
5183 QCBORItem Item;
5184 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5185 if(uError) {
5186 pMe->uLastError = (uint8_t)uError;
5187 return;
5188 }
5189
5190 const TagSpecification TagSpec =
5191 {
5192 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005193 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5194 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5195 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005196 };
5197
Laurence Lundblade93d89472020-10-03 22:30:50 -07005198 ProcessMantissaAndExponentBig(pMe,
5199 TagSpec,
5200 &Item,
5201 MantissaBuffer,
5202 pMantissa,
5203 pbMantissaIsNegative,
5204 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005205}
5206
5207
5208/*
5209 Public function, see header qcbor/qcbor_decode.h file
5210*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005211void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005212 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005213 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005214 UsefulBuf BufferForMantissa,
5215 UsefulBufC *pMantissa,
5216 bool *pbIsNegative,
5217 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005218{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005219 if(pMe->uLastError != QCBOR_SUCCESS) {
5220 return;
5221 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005222
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005223 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005224 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005225 if(pMe->uLastError != QCBOR_SUCCESS) {
5226 return;
5227 }
5228
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005229 const TagSpecification TagSpec =
5230 {
5231 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005232 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5233 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5234 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005235 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005236
Laurence Lundblade93d89472020-10-03 22:30:50 -07005237 ProcessMantissaAndExponentBig(pMe,
5238 TagSpec,
5239 &Item,
5240 BufferForMantissa,
5241 pMantissa,
5242 pbIsNegative,
5243 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005244}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005245
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005246
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005247/*
5248 Public function, see header qcbor/qcbor_decode.h file
5249*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005250void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005251 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005252 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005253 UsefulBuf BufferForMantissa,
5254 UsefulBufC *pMantissa,
5255 bool *pbIsNegative,
5256 int64_t *pnExponent)
5257{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005258 if(pMe->uLastError != QCBOR_SUCCESS) {
5259 return;
5260 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005261
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005262 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005263 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5264 if(pMe->uLastError != QCBOR_SUCCESS) {
5265 return;
5266 }
5267
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005268 const TagSpecification TagSpec =
5269 {
5270 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005271 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5272 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5273 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005274 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005275
5276 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5277}
5278
5279
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005280/*
5281 Public function, see header qcbor/qcbor_decode.h file
5282*/
5283void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5284 uint8_t uTagRequirement,
5285 int64_t *pnMantissa,
5286 int64_t *pnExponent)
5287{
5288 if(pMe->uLastError != QCBOR_SUCCESS) {
5289 return;
5290 }
5291
5292 QCBORItem Item;
5293 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5294 if(uError) {
5295 pMe->uLastError = (uint8_t)uError;
5296 return;
5297 }
5298 const TagSpecification TagSpec =
5299 {
5300 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005301 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5302 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5303 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005304 };
5305
5306 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5307}
5308
5309
5310/*
5311 Public function, see header qcbor/qcbor_decode.h file
5312*/
5313void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005314 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005315 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005316 int64_t *pnMantissa,
5317 int64_t *pnExponent)
5318{
5319 if(pMe->uLastError != QCBOR_SUCCESS) {
5320 return;
5321 }
5322
5323 QCBORItem Item;
5324 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5325 if(pMe->uLastError != QCBOR_SUCCESS) {
5326 return;
5327 }
5328
5329 const TagSpecification TagSpec =
5330 {
5331 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005332 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5333 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5334 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005335 };
5336
5337 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5338}
5339
5340
5341/*
5342 Public function, see header qcbor/qcbor_decode.h file
5343*/
5344void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005345 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005346 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005347 int64_t *pnMantissa,
5348 int64_t *pnExponent)
5349{
5350 if(pMe->uLastError != QCBOR_SUCCESS) {
5351 return;
5352 }
5353
5354 QCBORItem Item;
5355 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5356 if(pMe->uLastError != QCBOR_SUCCESS) {
5357 return;
5358 }
5359
5360 const TagSpecification TagSpec =
5361 {
5362 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005363 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5364 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5365 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005366 };
5367
5368 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5369}
5370
5371
5372/*
5373 Public function, see header qcbor/qcbor_decode.h file
5374*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005375void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5376 uint8_t uTagRequirement,
5377 UsefulBuf MantissaBuffer,
5378 UsefulBufC *pMantissa,
5379 bool *pbMantissaIsNegative,
5380 int64_t *pnExponent)
5381{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005382 if(pMe->uLastError != QCBOR_SUCCESS) {
5383 return;
5384 }
5385
5386 QCBORItem Item;
5387 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5388 if(uError) {
5389 pMe->uLastError = (uint8_t)uError;
5390 return;
5391 }
5392
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005393 const TagSpecification TagSpec =
5394 {
5395 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005396 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5397 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5398 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005399 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005400
5401 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005402}
5403
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005404
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005405/*
5406 Public function, see header qcbor/qcbor_decode.h file
5407*/
5408void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005409 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005410 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005411 UsefulBuf BufferForMantissa,
5412 UsefulBufC *pMantissa,
5413 bool *pbIsNegative,
5414 int64_t *pnExponent)
5415{
5416 if(pMe->uLastError != QCBOR_SUCCESS) {
5417 return;
5418 }
5419
5420 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005421 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5422 if(pMe->uLastError != QCBOR_SUCCESS) {
5423 return;
5424 }
5425
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005426 const TagSpecification TagSpec =
5427 {
5428 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005429 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5430 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5431 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005432 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005433
Laurence Lundblade93d89472020-10-03 22:30:50 -07005434 ProcessMantissaAndExponentBig(pMe,
5435 TagSpec,
5436 &Item,
5437 BufferForMantissa,
5438 pMantissa,
5439 pbIsNegative,
5440 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005441}
5442
5443
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005444/*
5445 Public function, see header qcbor/qcbor_decode.h file
5446*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005447void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005448 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005449 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005450 UsefulBuf BufferForMantissa,
5451 UsefulBufC *pMantissa,
5452 bool *pbIsNegative,
5453 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005454{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005455 if(pMe->uLastError != QCBOR_SUCCESS) {
5456 return;
5457 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005458
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005459 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005460 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5461 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005462 return;
5463 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005464
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005465 const TagSpecification TagSpec =
5466 {
5467 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005468 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5469 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5470 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005471 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005472
Laurence Lundblade93d89472020-10-03 22:30:50 -07005473 ProcessMantissaAndExponentBig(pMe,
5474 TagSpec,
5475 &Item,
5476 BufferForMantissa,
5477 pMantissa,
5478 pbIsNegative,
5479 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005480}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005481
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005482#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */