blob: 001a778206e9f29705c214201d427a4ec32d4fc8 [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
2033QCBORError
2034QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2035{
2036 QCBORError uErr;
2037 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2038 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002039 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2040 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2041 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002042 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002043}
2044
2045
2046/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002047 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002048 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002049void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2050{
2051 if(pMe->uLastError != QCBOR_SUCCESS) {
2052 return;
2053 }
2054
2055 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2056}
2057
2058
2059/*
2060 Public function, see header qcbor/qcbor_decode.h file
2061 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002062QCBORError
2063QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2064 QCBORItem *pDecodedItem,
2065 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002066{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002067 QCBORError nReturn;
2068
2069 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2070 if(nReturn != QCBOR_SUCCESS) {
2071 return nReturn;
2072 }
2073
2074 if(pTags != NULL) {
2075 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002076 // Reverse the order because pTags is reverse of
2077 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002078 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2079 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002080 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002081 }
2082 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2083 return QCBOR_ERR_TOO_MANY_TAGS;
2084 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002085 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002086 pTags->uNumUsed++;
2087 }
2088 }
2089
2090 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002091}
2092
2093
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002094/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302095 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302096 next one down. If a layer has no work to do for a particular item
2097 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002098
Laurence Lundblade59289e52019-12-30 13:44:37 -08002099 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2100 tagged data items, turning them into the local C representation.
2101 For the most simple it is just associating a QCBOR_TYPE with the data. For
2102 the complex ones that an aggregate of data items, there is some further
2103 decoding and a little bit of recursion.
2104
2105 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302106 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302107 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002108 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002109
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302110 - GetNext_MapEntry -- This handles the combining of two
2111 items, the label and the data, that make up a map entry.
2112 It only does work on maps. It combines the label and data
2113 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002114
Laurence Lundblade59289e52019-12-30 13:44:37 -08002115 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2116 tags into bit flags associated with the data item. No actual decoding
2117 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002118
Laurence Lundblade59289e52019-12-30 13:44:37 -08002119 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302120 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302121 string allocater to create contiguous space for the item. It
2122 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002123
Laurence Lundblade59289e52019-12-30 13:44:37 -08002124 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2125 atomic data item has a "major type", an integer "argument" and optionally
2126 some content. For text and byte strings, the content is the bytes
2127 that make up the string. These are the smallest data items that are
2128 considered to be well-formed. The content may also be other data items in
2129 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002130
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002131 Roughly this takes 300 bytes of stack for vars. Need to
2132 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002133
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302134 */
2135
2136
2137/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002138 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002139 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002140bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002141 const QCBORItem *pItem,
2142 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002143{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002144 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2145 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002146 break;
2147 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002148 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002149 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002150 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002151 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002152
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002153 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002154}
2155
2156
2157/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002158 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002159 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002160QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002161{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002162 QCBORError uReturn = me->uLastError;
2163
2164 if(uReturn != QCBOR_SUCCESS) {
2165 goto Done;
2166 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002167
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002168 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002169 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002170 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002171 goto Done;
2172 }
2173
2174 // Error out if not all the bytes are consumed
2175 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002176 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002177 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002178
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002179Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302180 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002181 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002182 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002183
Laurence Lundblade085d7952020-07-24 10:26:30 -07002184 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002185}
2186
2187
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002188/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002189 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002190*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002191// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002192uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2193 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002194 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002195{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002196 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2197 return CBOR_TAG_INVALID64;
2198 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002199 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2200 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002201 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002202 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002203 }
2204}
2205
Laurence Lundblade9b334962020-08-27 10:55:53 -07002206/*
2207 Public function, see header qcbor/qcbor_decode.h file
2208*/
2209uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2210 uint32_t uIndex)
2211{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002212 if(pMe->uLastError != QCBOR_SUCCESS) {
2213 return CBOR_TAG_INVALID64;
2214 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002215 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2216 return CBOR_TAG_INVALID64;
2217 } else {
2218 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2219 }
2220}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002221
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002222/*
2223
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002224Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002225
Laurence Lundbladeee851742020-01-08 08:37:05 -08002226 - Hit end of input before it was expected while decoding type and
2227 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002228
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002229 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002230
Laurence Lundbladeee851742020-01-08 08:37:05 -08002231 - Hit end of input while decoding a text or byte string
2232 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002233
Laurence Lundbladeee851742020-01-08 08:37:05 -08002234 - Encountered conflicting tags -- e.g., an item is tagged both a date
2235 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002236
Laurence Lundbladeee851742020-01-08 08:37:05 -08002237 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002238 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002239
Laurence Lundbladeee851742020-01-08 08:37:05 -08002240 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002241 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002242
Laurence Lundbladeee851742020-01-08 08:37:05 -08002243 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2244 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002245
Laurence Lundbladeee851742020-01-08 08:37:05 -08002246 - The type of a map label is not a string or int
2247 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002248
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002249 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002250
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002251 */
2252
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002253
2254
Laurence Lundbladef6531662018-12-04 10:42:22 +09002255
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002256/* ===========================================================================
2257 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002258
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002259 This implements a simple sting allocator for indefinite length
2260 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2261 implements the function type QCBORStringAllocate and allows easy
2262 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002263
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002264 This particular allocator is built-in for convenience. The caller
2265 can implement their own. All of this following code will get
2266 dead-stripped if QCBORDecode_SetMemPool() is not called.
2267
2268 This is a very primitive memory allocator. It does not track
2269 individual allocations, only a high-water mark. A free or
2270 reallocation must be of the last chunk allocated.
2271
2272 The size of the pool and offset to free memory are packed into the
2273 first 8 bytes of the memory pool so we don't have to keep them in
2274 the decode context. Since the address of the pool may not be
2275 aligned, they have to be packed and unpacked as if they were
2276 serialized data of the wire or such.
2277
2278 The sizes packed in are uint32_t to be the same on all CPU types
2279 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002280 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002281
2282
Laurence Lundbladeee851742020-01-08 08:37:05 -08002283static inline int
2284MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002285{
2286 // Use of UsefulInputBuf is overkill, but it is convenient.
2287 UsefulInputBuf UIB;
2288
Laurence Lundbladeee851742020-01-08 08:37:05 -08002289 // Just assume the size here. It was checked during SetUp so
2290 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002291 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002292 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2293 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2294 return UsefulInputBuf_GetError(&UIB);
2295}
2296
2297
Laurence Lundbladeee851742020-01-08 08:37:05 -08002298static inline int
2299MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002300{
2301 // Use of UsefulOutBuf is overkill, but convenient. The
2302 // length check performed here is useful.
2303 UsefulOutBuf UOB;
2304
2305 UsefulOutBuf_Init(&UOB, Pool);
2306 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2307 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2308 return UsefulOutBuf_GetError(&UOB);
2309}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002310
2311
2312/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002313 Internal function for an allocation, reallocation free and destuct.
2314
2315 Having only one function rather than one each per mode saves space in
2316 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002317
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002318 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2319 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002320static UsefulBuf
2321MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002322{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002323 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002324
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002325 uint32_t uPoolSize;
2326 uint32_t uFreeOffset;
2327
2328 if(uNewSize > UINT32_MAX) {
2329 // This allocator is only good up to 4GB. This check should
2330 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2331 goto Done;
2332 }
2333 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2334
2335 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2336 goto Done;
2337 }
2338
2339 if(uNewSize) {
2340 if(pMem) {
2341 // REALLOCATION MODE
2342 // Calculate pointer to the end of the memory pool. It is
2343 // assumed that pPool + uPoolSize won't wrap around by
2344 // assuming the caller won't pass a pool buffer in that is
2345 // not in legitimate memory space.
2346 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2347
2348 // Check that the pointer for reallocation is in the range of the
2349 // pool. This also makes sure that pointer math further down
2350 // doesn't wrap under or over.
2351 if(pMem >= pPool && pMem < pPoolEnd) {
2352 // Offset to start of chunk for reallocation. This won't
2353 // wrap under because of check that pMem >= pPool. Cast
2354 // is safe because the pool is always less than UINT32_MAX
2355 // because of check in QCBORDecode_SetMemPool().
2356 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2357
2358 // Check to see if the allocation will fit. uPoolSize -
2359 // uMemOffset will not wrap under because of check that
2360 // pMem is in the range of the uPoolSize by check above.
2361 if(uNewSize <= uPoolSize - uMemOffset) {
2362 ReturnValue.ptr = pMem;
2363 ReturnValue.len = uNewSize;
2364
2365 // Addition won't wrap around over because uNewSize was
2366 // checked to be sure it is less than the pool size.
2367 uFreeOffset = uMemOffset + uNewSize32;
2368 }
2369 }
2370 } else {
2371 // ALLOCATION MODE
2372 // uPoolSize - uFreeOffset will not underflow because this
2373 // pool implementation makes sure uFreeOffset is always
2374 // smaller than uPoolSize through this check here and
2375 // reallocation case.
2376 if(uNewSize <= uPoolSize - uFreeOffset) {
2377 ReturnValue.len = uNewSize;
2378 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002379 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002380 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002381 }
2382 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002383 if(pMem) {
2384 // FREE MODE
2385 // Cast is safe because of limit on pool size in
2386 // QCBORDecode_SetMemPool()
2387 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2388 } else {
2389 // DESTRUCT MODE
2390 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002391 }
2392 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002393
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002394 UsefulBuf Pool = {pPool, uPoolSize};
2395 MemPool_Pack(Pool, uFreeOffset);
2396
2397Done:
2398 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002399}
2400
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002401
Laurence Lundbladef6531662018-12-04 10:42:22 +09002402/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002403 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002404 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002405QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2406 UsefulBuf Pool,
2407 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002408{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002409 // The pool size and free mem offset are packed into the beginning
2410 // of the pool memory. This compile time check make sure the
2411 // constant in the header is correct. This check should optimize
2412 // down to nothing.
2413 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002414 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002415 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002416
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002417 // The pool size and free offset packed in to the beginning of pool
2418 // memory are only 32-bits. This check will optimize out on 32-bit
2419 // machines.
2420 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002421 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002422 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002423
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002424 // This checks that the pool buffer given is big enough.
2425 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002426 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002427 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002428
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002429 pMe->StringAllocator.pfAllocator = MemPool_Function;
2430 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2431 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002432
Laurence Lundblade30816f22018-11-10 13:40:22 +07002433 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002434}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002435
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002436
2437
Laurence Lundblade9b334962020-08-27 10:55:53 -07002438static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2439{
2440 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2441}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002442
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002443
2444/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002445 Consume an entire map or array (and do next to
2446 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002447 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002448static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002449ConsumeItem(QCBORDecodeContext *pMe,
2450 const QCBORItem *pItemToConsume,
2451 uint_fast8_t *puNextNestLevel)
2452{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002453 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002454 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002455
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002456 // If it is a map or array, this will tell if it is empty.
2457 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2458
2459 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2460 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002461
Laurence Lundblade1341c592020-04-11 14:19:05 -07002462 /* This works for definite and indefinite length
2463 * maps and arrays by using the nesting level
2464 */
2465 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002466 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002467 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002468 goto Done;
2469 }
2470 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002471
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002472 *puNextNestLevel = Item.uNextNestLevel;
2473
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002474 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002475
Laurence Lundblade1341c592020-04-11 14:19:05 -07002476 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002477 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002478 /* Just pass the nesting level through */
2479 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2480
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002481 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002482 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002483
2484Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002485 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002486}
2487
2488
Laurence Lundblade1341c592020-04-11 14:19:05 -07002489/* Return true if the labels in Item1 and Item2 are the same.
2490 Works only for integer and string labels. Returns false
2491 for any other type. */
2492static inline bool
2493MatchLabel(QCBORItem Item1, QCBORItem Item2)
2494{
2495 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2496 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2497 return true;
2498 }
2499 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002500 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002501 return true;
2502 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002503 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002504 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2505 return true;
2506 }
2507 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2508 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2509 return true;
2510 }
2511 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002512
Laurence Lundblade1341c592020-04-11 14:19:05 -07002513 /* Other label types are never matched */
2514 return false;
2515}
2516
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002517
2518/*
2519 Returns true if Item1 and Item2 are the same type
2520 or if either are of QCBOR_TYPE_ANY.
2521 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002522static inline bool
2523MatchType(QCBORItem Item1, QCBORItem Item2)
2524{
2525 if(Item1.uDataType == Item2.uDataType) {
2526 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002527 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002528 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002529 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002530 return true;
2531 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002532 return false;
2533}
2534
2535
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002536/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002537 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002538
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002539 @param[in] pMe The decode context to search.
2540 @param[in,out] pItemArray The items to search for and the items found.
2541 @param[out] puOffset Byte offset of last item matched.
2542 @param[in] pCBContext Context for the not-found item call back.
2543 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002544
2545 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2546
Laurence Lundblade93d89472020-10-03 22:30:50 -07002547 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2548 were found for one of the labels being
2549 search for. This duplicate detection is
2550 only performed for items in pItemArray,
2551 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002552
Laurence Lundblade93d89472020-10-03 22:30:50 -07002553 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2554 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002555
2556 @retval Also errors returned by QCBORDecode_GetNext().
2557
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002558 On input pItemArray contains a list of labels and data types
2559 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002560
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002561 On output the fully retrieved items are filled in with
2562 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002563
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002564 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002565
2566 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002567 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002568static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002569MapSearch(QCBORDecodeContext *pMe,
2570 QCBORItem *pItemArray,
2571 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002572 void *pCBContext,
2573 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002574{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002575 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002576 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002577
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002578 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002579 uReturn = pMe->uLastError;
2580 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002581 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002582
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002583 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002584 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2585 /* QCBOR_TYPE_NONE as first item indicates just looking
2586 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002587 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2588 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002589 }
2590
Laurence Lundblade085d7952020-07-24 10:26:30 -07002591 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2592 // It is an empty bounded array or map
2593 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2594 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002595 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002596 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002597 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002598 // Nothing is ever found in an empty array or map. All items
2599 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002600 uReturn = QCBOR_SUCCESS;
2601 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002602 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002603 }
2604
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002605 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002606 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2607
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002608 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002609 UsefulInputBuf_Seek(&(pMe->InBuf),
2610 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002611
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002612 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002613 Loop over all the items in the map or array. Each item
2614 could be a map or array, but label matching is only at
2615 the main level. This handles definite and indefinite
2616 length maps and arrays. The only reason this is ever
2617 called on arrays is to find their end position.
2618
2619 This will always run over all items in order to do
2620 duplicate detection.
2621
2622 This will exit with failure if it encounters an
2623 unrecoverable error, but continue on for recoverable
2624 errors.
2625
2626 If a recoverable error occurs on a matched item, then
2627 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002628 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002629 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002630 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002631 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002632 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002633 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002634
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002635 /* Get the item */
2636 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002637 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2638 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002639 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002640 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002641 goto Done;
2642 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002643 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002644 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002645 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002646 goto Done;
2647 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002648
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002649 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002650 bool bMatched = false;
2651 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2652 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002653 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002654 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2655 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002656 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002657 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002658 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002659 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002660 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002661 goto Done;
2662 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002663
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002664 if(uResult != QCBOR_SUCCESS) {
2665 uReturn = uResult;
2666 goto Done;
2667 }
2668
Laurence Lundblade1341c592020-04-11 14:19:05 -07002669 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002670 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002671 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002672 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002673 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002674 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002675 bMatched = true;
2676 }
2677 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002678
2679
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002680 if(!bMatched && pfCallback != NULL) {
2681 /*
2682 Call the callback on unmatched labels.
2683 (It is tempting to do duplicate detection here, but that would
2684 require dynamic memory allocation because the number of labels
2685 that might be encountered is unbounded.)
2686 */
2687 uReturn = (*pfCallback)(pCBContext, &Item);
2688 if(uReturn != QCBOR_SUCCESS) {
2689 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002690 }
2691 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002692
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002693 /*
2694 Consume the item whether matched or not. This
2695 does the work of traversing maps and array and
2696 everything in them. In this loop only the
2697 items at the current nesting level are examined
2698 to match the labels.
2699 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002700 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002701 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002702 goto Done;
2703 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002704
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002705 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002706
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002707 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002708
2709 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002710
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002711 // Check here makes sure that this won't accidentally be
2712 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002713 // QCBOR_MAX_DECODE_INPUT_SIZE.
2714 if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
2715 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2716 goto Done;
2717 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002718 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2719 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002720
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002721 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002722 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2723
2724 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002725 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002726 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002727 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002728 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2729 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002730 }
2731 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002732
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002733 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002734}
2735
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002736
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002737/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002738 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002739*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002740void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2741 int64_t nLabel,
2742 uint8_t uQcborType,
2743 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002744{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002745 if(pMe->uLastError != QCBOR_SUCCESS) {
2746 return;
2747 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002748
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002749 QCBORItem OneItemSeach[2];
2750 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2751 OneItemSeach[0].label.int64 = nLabel;
2752 OneItemSeach[0].uDataType = uQcborType;
2753 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002754
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002755 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002756
2757 *pItem = OneItemSeach[0];
2758
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002759 if(uReturn != QCBOR_SUCCESS) {
2760 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002761 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002762 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002763 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002764 }
2765
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002766 Done:
2767 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002768}
2769
2770
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002771/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002772 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002773*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002774void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2775 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002776 uint8_t uQcborType,
2777 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002778{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002779 if(pMe->uLastError != QCBOR_SUCCESS) {
2780 return;
2781 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002782
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002783 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002784 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2785 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2786 OneItemSeach[0].uDataType = uQcborType;
2787 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002788
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002789 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2790 if(uReturn != QCBOR_SUCCESS) {
2791 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002792 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002793 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002794 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002795 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002796 }
2797
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002798 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002799
2800Done:
2801 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002802}
2803
2804
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002805
Laurence Lundblade93d89472020-10-03 22:30:50 -07002806static QCBORError
2807CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002808{
2809 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2810 if(uDataType == puTypeList[i]) {
2811 return QCBOR_SUCCESS;
2812 }
2813 }
2814 return QCBOR_ERR_UNEXPECTED_TYPE;
2815}
2816
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002817
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002818/**
2819 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002820 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002821
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002822 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2823 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002824
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002825 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2826 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002827 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002828static QCBORError
2829CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002830{
2831 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2832 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2833 /* There are tags that QCBOR couldn't process on this item and
2834 the caller has told us there should not be. */
2835 return QCBOR_ERR_UNEXPECTED_TYPE;
2836 }
2837
2838 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2839 const int nItemType = pItem->uDataType;
2840
2841 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2842 // Must match the tag and only the tag
2843 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2844 }
2845
2846 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2847 if(uReturn == QCBOR_SUCCESS) {
2848 return QCBOR_SUCCESS;
2849 }
2850
2851 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2852 /* Must match the content type and only the content type.
2853 There was no match just above so it is a fail. */
2854 return QCBOR_ERR_UNEXPECTED_TYPE;
2855 }
2856
2857 /* If here it can match either the tag or the content
2858 and it hasn't matched the content, so the end
2859 result is whether it matches the tag. This is
2860 also the case that the CBOR standard discourages. */
2861
2862 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2863}
2864
Laurence Lundblade9b334962020-08-27 10:55:53 -07002865
Laurence Lundblade9b334962020-08-27 10:55:53 -07002866
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002867// This could be semi-private if need be
2868static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002869void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2870 int64_t nLabel,
2871 TagSpecification TagSpec,
2872 QCBORItem *pItem)
2873{
2874 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2875 if(pMe->uLastError != QCBOR_SUCCESS) {
2876 return;
2877 }
2878
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002879 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002880}
2881
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002882
2883// This could be semi-private if need be
2884static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002885void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2886 const char *szLabel,
2887 TagSpecification TagSpec,
2888 QCBORItem *pItem)
2889{
2890 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2891 if(pMe->uLastError != QCBOR_SUCCESS) {
2892 return;
2893 }
2894
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002895 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002896}
2897
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002898// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002899void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2900 int64_t nLabel,
2901 TagSpecification TagSpec,
2902 UsefulBufC *pString)
2903{
2904 QCBORItem Item;
2905 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2906 if(pMe->uLastError == QCBOR_SUCCESS) {
2907 *pString = Item.val.string;
2908 }
2909}
2910
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002911// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002912void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2913 const char * szLabel,
2914 TagSpecification TagSpec,
2915 UsefulBufC *pString)
2916{
2917 QCBORItem Item;
2918 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2919 if(pMe->uLastError == QCBOR_SUCCESS) {
2920 *pString = Item.val.string;
2921 }
2922}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002923
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002924/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002925 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002926*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002927void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002928{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002929 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2930 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002931}
2932
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002933/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002934 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002935*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002936void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2937 QCBORItem *pItemList,
2938 void *pCallbackCtx,
2939 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002940{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002941 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2942 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002943}
2944
2945
Laurence Lundblade34691b92020-05-18 22:25:25 -07002946static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002947{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002948 // The first item in pSearch is the one that is to be
2949 // entered. It should be the only one filled in. Any other
2950 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07002951 if(pMe->uLastError != QCBOR_SUCCESS) {
2952 // Already in error state; do nothing.
2953 return;
2954 }
2955
2956 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002957 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002958 if(pMe->uLastError != QCBOR_SUCCESS) {
2959 return;
2960 }
2961
Laurence Lundblade9b334962020-08-27 10:55:53 -07002962 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002963 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002964 return;
2965 }
2966
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002967 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002968 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002969
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002970 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002971 be at the right place.
2972
2973 The UsefulInBuf offset could be anywhere, so no assumption is
2974 made about it.
2975
2976 No assumption is made about the pre-order nesting level either.
2977
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002978 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002979 the map level that is being entered.
2980 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002981 /* Seek to the data item that is the map or array */
2982 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002983
2984 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002985
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07002986 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002987}
2988
2989
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002990/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002991 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002992*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002993void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002994{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002995 QCBORItem OneItemSeach[2];
2996 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2997 OneItemSeach[0].label.int64 = nLabel;
2998 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2999 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003000
Laurence Lundblade9b334962020-08-27 10:55:53 -07003001 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003002 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003003}
3004
3005
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003006/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003007 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003008*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003009void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003010{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003011 QCBORItem OneItemSeach[2];
3012 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3013 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3014 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3015 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003016
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003017 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003018}
3019
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003020/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003021 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003022*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003023void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003024{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003025 QCBORItem OneItemSeach[2];
3026 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3027 OneItemSeach[0].label.int64 = nLabel;
3028 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3029 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003030
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003031 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003032}
3033
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003034/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003035 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003036*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003037void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3038{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003039 QCBORItem OneItemSeach[2];
3040 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3041 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3042 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3043 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003044
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003045 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003046}
3047
3048
Laurence Lundblade02625d42020-06-25 14:41:41 -07003049// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003050void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003051{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003052 QCBORError uErr;
3053
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003054 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003055 if(pMe->uLastError != QCBOR_SUCCESS) {
3056 // Already in error state; do nothing.
3057 return;
3058 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003059
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003060 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003061 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003062 uErr = QCBORDecode_GetNext(pMe, &Item);
3063 if(uErr != QCBOR_SUCCESS) {
3064 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003065 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003066 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003067 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3068 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003069 }
3070
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003071 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003072
3073
Laurence Lundbladef0499502020-08-01 11:55:57 -07003074 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003075 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003076 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3077 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003078 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003079 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3080 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003081 // Special case to increment nesting level for zero-length maps
3082 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003083 DecodeNesting_Descend(&(pMe->nesting), uType);
3084 }
3085
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003086 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003087
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003088 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3089 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003090
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003091 if(pItem != NULL) {
3092 *pItem = Item;
3093 }
3094
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003095Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003096 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003097}
3098
Laurence Lundblade02625d42020-06-25 14:41:41 -07003099
3100/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003101 This is the common work for exiting a level that is a bounded map,
3102 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003103
3104 One chunk of work is to set up the pre-order traversal so it is at
3105 the item just after the bounded map, array or bstr that is being
3106 exited. This is somewhat complex.
3107
3108 The other work is to level-up the bounded mode to next higest bounded
3109 mode or the top level if there isn't one.
3110 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003111static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003112ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003113{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003114 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003115
Laurence Lundblade02625d42020-06-25 14:41:41 -07003116 /*
3117 First the pre-order-traversal byte offset is positioned to the
3118 item just after the bounded mode item that was just consumed.
3119 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003120 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3121
Laurence Lundblade02625d42020-06-25 14:41:41 -07003122 /*
3123 Next, set the current nesting level to one above the bounded level
3124 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003125
Laurence Lundblade02625d42020-06-25 14:41:41 -07003126 DecodeNesting_CheckBoundedType() is always called before this and
3127 makes sure pCurrentBounded is valid.
3128 */
3129 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3130
3131 /*
3132 This does the complex work of leveling up the pre-order traversal
3133 when the end of a map or array or another bounded level is
3134 reached. It may do nothing, or ascend all the way to the top
3135 level.
3136 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003137 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003138 if(uErr != QCBOR_SUCCESS) {
3139 goto Done;
3140 }
3141
Laurence Lundblade02625d42020-06-25 14:41:41 -07003142 /*
3143 This makes the next highest bounded level the current bounded
3144 level. If there is no next highest level, then no bounded mode is
3145 in effect.
3146 */
3147 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003148
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003149 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003150
3151Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003152 return uErr;
3153}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003154
Laurence Lundblade02625d42020-06-25 14:41:41 -07003155
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003156// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003157void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003158{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003159 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003160 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003161 return;
3162 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003163
Laurence Lundblade02625d42020-06-25 14:41:41 -07003164 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003165
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003166 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003167 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003168 goto Done;
3169 }
3170
Laurence Lundblade02625d42020-06-25 14:41:41 -07003171 /*
3172 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003173 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003174 from previous map search, then do a dummy search.
3175 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003176 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003177 QCBORItem Dummy;
3178 Dummy.uLabelType = QCBOR_TYPE_NONE;
3179 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3180 if(uErr != QCBOR_SUCCESS) {
3181 goto Done;
3182 }
3183 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003184
Laurence Lundblade02625d42020-06-25 14:41:41 -07003185 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003186
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003187Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003188 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003189}
3190
3191
Laurence Lundblade1341c592020-04-11 14:19:05 -07003192
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003193static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003194 const QCBORItem *pItem,
3195 uint8_t uTagRequirement,
3196 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003197{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003198 if(pBstr) {
3199 *pBstr = NULLUsefulBufC;
3200 }
3201
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003202 if(pMe->uLastError != QCBOR_SUCCESS) {
3203 // Already in error state; do nothing.
3204 return pMe->uLastError;
3205 }
3206
3207 QCBORError uError = QCBOR_SUCCESS;
3208
3209 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3210 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3211 goto Done;;
3212 }
3213
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003214 const TagSpecification TagSpec =
3215 {
3216 uTagRequirement,
3217 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3218 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3219 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003220
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003221 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003222 if(uError != QCBOR_SUCCESS) {
3223 goto Done;
3224 }
3225
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003226 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003227 // Reverse the decrement done by GetNext() for the bstr so the
3228 // increment in NestLevelAscender() called by ExitBoundedLevel()
3229 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003230 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003231 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003232
3233 if(pBstr) {
3234 *pBstr = pItem->val.string;
3235 }
3236
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003237 // This saves the current length of the UsefulInputBuf and then
3238 // narrows the UsefulInputBuf to start and length of the wrapped
3239 // CBOR that is being entered.
3240 //
3241 // This makes sure the length is less than
3242 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3243 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3244 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3245 // the casts safe. uEndOfBstr will always be less than
3246 // uPreviousLength because of the way UsefulInputBuf works so there
3247 // is no need to check it. There is also a range check in the
3248 // seek.
3249 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003250 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003251 // amount to much code.
3252 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3253 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003254 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003255 goto Done;
3256 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003257 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003258 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003259 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003260
Laurence Lundblade02625d42020-06-25 14:41:41 -07003261 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003262 (uint32_t)uPreviousLength,
3263 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003264Done:
3265 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003266}
3267
3268
Laurence Lundblade02625d42020-06-25 14:41:41 -07003269/*
3270 Public function, see header qcbor/qcbor_decode.h file
3271 */
3272void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003273 uint8_t uTagRequirement,
3274 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003275{
3276 if(pMe->uLastError != QCBOR_SUCCESS) {
3277 // Already in error state; do nothing.
3278 return;
3279 }
3280
3281 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003282 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003283 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3284 if(pMe->uLastError != QCBOR_SUCCESS) {
3285 return;
3286 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003287
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003288 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003289 &Item,
3290 uTagRequirement,
3291 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003292}
3293
3294
Laurence Lundblade02625d42020-06-25 14:41:41 -07003295/*
3296 Public function, see header qcbor/qcbor_decode.h file
3297 */
3298void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003299 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003300 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003301 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003302{
3303 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003304 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003305
Laurence Lundblade93d89472020-10-03 22:30:50 -07003306 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3307 &Item,
3308 uTagRequirement,
3309 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003310}
3311
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003312
Laurence Lundblade02625d42020-06-25 14:41:41 -07003313/*
3314 Public function, see header qcbor/qcbor_decode.h file
3315 */
3316void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003317 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003318 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003319 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003320{
3321 QCBORItem Item;
3322 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3323
Laurence Lundblade93d89472020-10-03 22:30:50 -07003324 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3325 &Item,
3326 uTagRequirement,
3327 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003328}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003329
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003330
Laurence Lundblade02625d42020-06-25 14:41:41 -07003331/*
3332 Public function, see header qcbor/qcbor_decode.h file
3333 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003334void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003335{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003336 if(pMe->uLastError != QCBOR_SUCCESS) {
3337 // Already in error state; do nothing.
3338 return;
3339 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003340
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003341 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003342 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003343 return;
3344 }
3345
3346 /*
3347 Reset the length of the UsefulInputBuf to what it was before
3348 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003349 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003350 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003351 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003352
3353
Laurence Lundblade02625d42020-06-25 14:41:41 -07003354 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003355 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003356}
3357
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003358
Laurence Lundbladee6430642020-03-14 21:15:44 -07003359
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003360
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003361
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003362
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003363
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003364
Laurence Lundblade93d89472020-10-03 22:30:50 -07003365static QCBORError
3366InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003367{
3368 switch(pItem->uDataType) {
3369 case QCBOR_TYPE_TRUE:
3370 *pBool = true;
3371 return QCBOR_SUCCESS;
3372 break;
3373
3374 case QCBOR_TYPE_FALSE:
3375 *pBool = false;
3376 return QCBOR_SUCCESS;
3377 break;
3378
3379 default:
3380 return QCBOR_ERR_UNEXPECTED_TYPE;
3381 break;
3382 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003383 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003384}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003385
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003386
Laurence Lundblade9b334962020-08-27 10:55:53 -07003387
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003388/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003389 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003390*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003391void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003392{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003393 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003394 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003395 return;
3396 }
3397
Laurence Lundbladec4537442020-04-14 18:53:22 -07003398 QCBORError nError;
3399 QCBORItem Item;
3400
3401 nError = QCBORDecode_GetNext(pMe, &Item);
3402 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003403 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003404 return;
3405 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003406 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003407}
3408
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003409
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003410/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003411 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003412*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003413void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003414{
3415 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003416 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003417
Laurence Lundblade9b334962020-08-27 10:55:53 -07003418 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003419}
3420
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003421
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003422/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003423 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003424*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003425void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3426{
3427 QCBORItem Item;
3428 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3429
Laurence Lundblade9b334962020-08-27 10:55:53 -07003430 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003431}
3432
3433
3434
Laurence Lundbladec7114722020-08-13 05:11:40 -07003435
3436static void ProcessEpochDate(QCBORDecodeContext *pMe,
3437 QCBORItem *pItem,
3438 uint8_t uTagRequirement,
3439 int64_t *pnTime)
3440{
3441 if(pMe->uLastError != QCBOR_SUCCESS) {
3442 // Already in error state, do nothing
3443 return;
3444 }
3445
3446 QCBORError uErr;
3447
3448 const TagSpecification TagSpec =
3449 {
3450 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003451 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3452 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003453 };
3454
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003455 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003456 if(uErr != QCBOR_SUCCESS) {
3457 goto Done;
3458 }
3459
3460 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3461 uErr = DecodeDateEpoch(pItem);
3462 if(uErr != QCBOR_SUCCESS) {
3463 goto Done;
3464 }
3465 }
3466
Laurence Lundblade9b334962020-08-27 10:55:53 -07003467 // Save the tags in the last item's tags in the decode context
3468 // for QCBORDecode_GetNthTagOfLast()
3469 CopyTags(pMe, pItem);
3470
Laurence Lundbladec7114722020-08-13 05:11:40 -07003471 *pnTime = pItem->val.epochDate.nSeconds;
3472
3473Done:
3474 pMe->uLastError = (uint8_t)uErr;
3475}
3476
3477
3478void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003479 uint8_t uTagRequirement,
3480 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003481{
3482 if(pMe->uLastError != QCBOR_SUCCESS) {
3483 // Already in error state, do nothing
3484 return;
3485 }
3486
3487 QCBORItem Item;
3488 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3489
3490 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3491}
3492
3493
3494void
3495QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3496 int64_t nLabel,
3497 uint8_t uTagRequirement,
3498 int64_t *pnTime)
3499{
3500 QCBORItem Item;
3501 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3502 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3503}
3504
3505
3506void
3507QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3508 const char *szLabel,
3509 uint8_t uTagRequirement,
3510 int64_t *pnTime)
3511{
3512 QCBORItem Item;
3513 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3514 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3515}
3516
3517
3518
3519
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003520void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3521 TagSpecification TagSpec,
3522 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003523{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003524 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003525 // Already in error state, do nothing
3526 return;
3527 }
3528
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003529 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003530 QCBORItem Item;
3531
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003532 uError = QCBORDecode_GetNext(pMe, &Item);
3533 if(uError != QCBOR_SUCCESS) {
3534 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003535 return;
3536 }
3537
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003538 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003539
3540 if(pMe->uLastError == QCBOR_SUCCESS) {
3541 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003542 } else {
3543 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003544 }
3545}
3546
Laurence Lundbladec4537442020-04-14 18:53:22 -07003547
3548
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003549
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003550static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003551 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003552 UsefulBufC *pValue,
3553 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003554{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003555 const TagSpecification TagSpec =
3556 {
3557 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003558 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3559 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003560 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003561
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003562 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003563 if(uErr != QCBOR_SUCCESS) {
3564 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003565 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003566
3567 *pValue = pItem->val.string;
3568
3569 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3570 *pbIsNegative = false;
3571 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3572 *pbIsNegative = true;
3573 }
3574
3575 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003576}
3577
3578
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003579/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003580 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003581 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003582void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3583 uint8_t uTagRequirement,
3584 UsefulBufC *pValue,
3585 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003586{
3587 if(pMe->uLastError != QCBOR_SUCCESS) {
3588 // Already in error state, do nothing
3589 return;
3590 }
3591
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003592 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003593 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3594 if(uError != QCBOR_SUCCESS) {
3595 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003596 return;
3597 }
3598
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003599 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003600}
3601
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003602
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003603/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003604 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003605*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003606void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3607 int64_t nLabel,
3608 uint8_t uTagRequirement,
3609 UsefulBufC *pValue,
3610 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003611{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003612 QCBORItem Item;
3613 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003614 if(pMe->uLastError != QCBOR_SUCCESS) {
3615 return;
3616 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003617
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003618 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003619}
3620
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003621
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003622/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003623 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003624*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003625void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3626 const char *szLabel,
3627 uint8_t uTagRequirement,
3628 UsefulBufC *pValue,
3629 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003630{
3631 QCBORItem Item;
3632 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003633 if(pMe->uLastError != QCBOR_SUCCESS) {
3634 return;
3635 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003636
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003637 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003638}
3639
3640
3641
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003642
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003643// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003644QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3645 const QCBORItem *pItem,
3646 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003647 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003648{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003649 const TagSpecification TagSpecText =
3650 {
3651 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003652 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3653 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003654 };
3655 const TagSpecification TagSpecBinary =
3656 {
3657 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003658 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3659 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003660 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003661
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003662 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003663
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003664 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003665 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003666 if(pbIsTag257 != NULL) {
3667 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003668 }
3669 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003670 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003671 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003672 if(pbIsTag257 != NULL) {
3673 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003674 }
3675 uReturn = QCBOR_SUCCESS;
3676
3677 } else {
3678 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3679 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003680
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003681 return uReturn;
3682}
3683
Laurence Lundblade93d89472020-10-03 22:30:50 -07003684// Improvement: add methods for wrapped CBOR, a simple alternate
3685// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003686
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003687
3688
3689
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003690#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003691
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003692typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003693
3694
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003695// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003696static QCBORError
3697Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003698{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003699 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003700
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003701 if(uResult != 0) {
3702 /* This loop will run a maximum of 19 times because
3703 * UINT64_MAX < 10 ^^ 19. More than that will cause
3704 * exit with the overflow error
3705 */
3706 for(; nExponent > 0; nExponent--) {
3707 if(uResult > UINT64_MAX / 10) {
3708 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3709 }
3710 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003711 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003712
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003713 for(; nExponent < 0; nExponent++) {
3714 uResult = uResult / 10;
3715 if(uResult == 0) {
3716 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3717 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003718 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003719 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003720 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003721
3722 *puResult = uResult;
3723
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003724 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003725}
3726
3727
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003728// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003729static QCBORError
3730Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003731{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003732 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003733
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003734 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003735
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003736 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003737 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003738 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003739 */
3740 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003741 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003742 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003743 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003744 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003745 nExponent--;
3746 }
3747
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003748 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003749 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003750 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3751 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003752 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003753 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003754 }
3755
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003756 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003757
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003758 return QCBOR_SUCCESS;
3759}
3760
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003761
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003762/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003763 Compute value with signed mantissa and signed result. Works with
3764 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003765 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003766static inline QCBORError ExponentiateNN(int64_t nMantissa,
3767 int64_t nExponent,
3768 int64_t *pnResult,
3769 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003770{
3771 uint64_t uResult;
3772
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003773 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003774 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003775 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3776
3777 // Do the exponentiation of the positive mantissa
3778 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3779 if(uReturn) {
3780 return uReturn;
3781 }
3782
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003783
Laurence Lundblade983500d2020-05-14 11:49:34 -07003784 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3785 of INT64_MIN. This assumes two's compliment representation where
3786 INT64_MIN is one increment farther from 0 than INT64_MAX.
3787 Trying to write -INT64_MIN doesn't work to get this because the
3788 compiler tries to work with an int64_t which can't represent
3789 -INT64_MIN.
3790 */
3791 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3792
3793 // Error out if too large
3794 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003795 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3796 }
3797
3798 // Casts are safe because of checks above
3799 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3800
3801 return QCBOR_SUCCESS;
3802}
3803
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003804
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003805/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003806 Compute value with signed mantissa and unsigned result. Works with
3807 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003808 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003809static inline QCBORError ExponentitateNU(int64_t nMantissa,
3810 int64_t nExponent,
3811 uint64_t *puResult,
3812 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003813{
3814 if(nMantissa < 0) {
3815 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3816 }
3817
3818 // Cast to unsigned is OK because of check for negative
3819 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3820 // Exponentiation is straight forward
3821 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3822}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003823
3824
3825/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003826 Compute value with signed mantissa and unsigned result. Works with
3827 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003828 */
3829static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3830 int64_t nExponent,
3831 uint64_t *puResult,
3832 fExponentiator pfExp)
3833{
3834 return (*pfExp)(uMantissa, nExponent, puResult);
3835}
3836
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003837#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3838
3839
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003840
3841
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003842
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003843static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003844{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003845 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003846
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003847 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003848 const uint8_t *pByte = BigNum.ptr;
3849 size_t uLen = BigNum.len;
3850 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003851 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003852 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003853 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003854 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003855 }
3856
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003857 *pResult = uResult;
3858 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003859}
3860
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003861
Laurence Lundblade887add82020-05-17 05:50:34 -07003862static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003863{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003864 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003865}
3866
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003867
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003868static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003869{
3870 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003871 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3872 if(uError) {
3873 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003874 }
3875 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3876 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003877 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003878}
3879
3880
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003881static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003882{
3883 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003884 /* The negative integer furthest from zero for a C int64_t is
3885 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3886 negative number in CBOR is computed as -n - 1 where n is the
3887 encoded integer, where n is what is in the variable BigNum. When
3888 converting BigNum to a uint64_t, the maximum value is thus
3889 INT64_MAX, so that when it -n - 1 is applied to it the result will
3890 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003891
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003892 -n - 1 <= INT64_MIN.
3893 -n - 1 <= -INT64_MAX - 1
3894 n <= INT64_MAX.
3895 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003896 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003897 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003898 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003899 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003900
3901 /// Now apply -n - 1. The cast is safe because
3902 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3903 // is the largest positive integer that an int64_t can
3904 // represent. */
3905 *pnResult = -(int64_t)uResult - 1;
3906
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003907 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003908}
3909
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003910
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003911
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003912
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003913
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003914/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003915Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003916
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003917\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003918
Laurence Lundblade93d89472020-10-03 22:30:50 -07003919\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
3920 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003921
3922\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3923
Laurence Lundblade93d89472020-10-03 22:30:50 -07003924\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
3925 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003926*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07003927static QCBORError
3928ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003929{
3930 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003931 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003932 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003933#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003934 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003935 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3936 http://www.cplusplus.com/reference/cmath/llround/
3937 */
3938 // Not interested in FE_INEXACT
3939 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003940 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3941 *pnValue = llround(pItem->val.dfnum);
3942 } else {
3943 *pnValue = lroundf(pItem->val.fnum);
3944 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003945 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
3946 // llround() shouldn't result in divide by zero, but catch
3947 // it here in case it unexpectedly does. Don't try to
3948 // distinguish between the various exceptions because it seems
3949 // they vary by CPU, compiler and OS.
3950 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003951 }
3952 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003953 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003954 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003955#else
3956 return QCBOR_ERR_HW_FLOAT_DISABLED;
3957#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003958 break;
3959
3960 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003961 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003962 *pnValue = pItem->val.int64;
3963 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003964 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003965 }
3966 break;
3967
3968 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003969 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003970 if(pItem->val.uint64 < INT64_MAX) {
3971 *pnValue = pItem->val.int64;
3972 } else {
3973 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3974 }
3975 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003976 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003977 }
3978 break;
3979
3980 default:
3981 return QCBOR_ERR_UNEXPECTED_TYPE;
3982 }
3983 return QCBOR_SUCCESS;
3984}
3985
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003986
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003987void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003988 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003989 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003990 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003991{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003992 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003993 return;
3994 }
3995
Laurence Lundbladee6430642020-03-14 21:15:44 -07003996 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003997 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3998 if(uError) {
3999 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004000 return;
4001 }
4002
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004003 if(pItem) {
4004 *pItem = Item;
4005 }
4006
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004007 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004008}
4009
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004010
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004011void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4012 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004013 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004014 int64_t *pnValue,
4015 QCBORItem *pItem)
4016{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004017 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004018 if(pMe->uLastError != QCBOR_SUCCESS) {
4019 return;
4020 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004021
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004022 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004023}
4024
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004025
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004026void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4027 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004028 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004029 int64_t *pnValue,
4030 QCBORItem *pItem)
4031{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004032 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004033 if(pMe->uLastError != QCBOR_SUCCESS) {
4034 return;
4035 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004036
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004037 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004038}
4039
4040
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004041/*
4042 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004043
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004044 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004045
Laurence Lundblade93d89472020-10-03 22:30:50 -07004046 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4047 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004048
4049 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4050
Laurence Lundblade93d89472020-10-03 22:30:50 -07004051 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4052 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004053 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004054static QCBORError
4055Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004056{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004057 switch(pItem->uDataType) {
4058
4059 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004060 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004061 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004062 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004063 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004064 }
4065 break;
4066
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004067 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004068 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004069 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004070 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004071 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004072 }
4073 break;
4074
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004075#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4076 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004077 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004078 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004079 pItem->val.expAndMantissa.nExponent,
4080 pnValue,
4081 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004082 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004083 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004084 }
4085 break;
4086
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004087 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004088 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004089 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004090 pItem->val.expAndMantissa.nExponent,
4091 pnValue,
4092 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004093 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004094 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004095 }
4096 break;
4097
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004098 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004099 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004100 int64_t nMantissa;
4101 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004102 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4103 if(uErr) {
4104 return uErr;
4105 }
4106 return ExponentiateNN(nMantissa,
4107 pItem->val.expAndMantissa.nExponent,
4108 pnValue,
4109 Exponentitate10);
4110 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004111 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004112 }
4113 break;
4114
4115 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004116 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004117 int64_t nMantissa;
4118 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004119 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4120 if(uErr) {
4121 return uErr;
4122 }
4123 return ExponentiateNN(nMantissa,
4124 pItem->val.expAndMantissa.nExponent,
4125 pnValue,
4126 Exponentitate10);
4127 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004128 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004129 }
4130 break;
4131
4132 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004133 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004134 int64_t nMantissa;
4135 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004136 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4137 if(uErr) {
4138 return uErr;
4139 }
4140 return ExponentiateNN(nMantissa,
4141 pItem->val.expAndMantissa.nExponent,
4142 pnValue,
4143 Exponentitate2);
4144 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004145 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004146 }
4147 break;
4148
4149 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004150 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004151 int64_t nMantissa;
4152 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004153 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4154 if(uErr) {
4155 return uErr;
4156 }
4157 return ExponentiateNN(nMantissa,
4158 pItem->val.expAndMantissa.nExponent,
4159 pnValue,
4160 Exponentitate2);
4161 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004162 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004163 }
4164 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004165#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4166
Laurence Lundbladee6430642020-03-14 21:15:44 -07004167
Laurence Lundbladec4537442020-04-14 18:53:22 -07004168 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004169 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004170}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004171
4172
Laurence Lundbladec4537442020-04-14 18:53:22 -07004173/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004174 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004175 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004176void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004177{
4178 QCBORItem Item;
4179
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004180 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004181
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004182 if(pMe->uLastError == QCBOR_SUCCESS) {
4183 // The above conversion succeeded
4184 return;
4185 }
4186
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004187 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004188 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004189 return;
4190 }
4191
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004192 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004193}
4194
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004195
4196/*
4197Public function, see header qcbor/qcbor_decode.h file
4198*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004199void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4200 int64_t nLabel,
4201 uint32_t uConvertTypes,
4202 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004203{
4204 QCBORItem Item;
4205
Laurence Lundblade93d89472020-10-03 22:30:50 -07004206 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4207 nLabel,
4208 uConvertTypes,
4209 pnValue,
4210 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004211
4212 if(pMe->uLastError == QCBOR_SUCCESS) {
4213 // The above conversion succeeded
4214 return;
4215 }
4216
4217 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4218 // The above conversion failed in a way that code below can't correct
4219 return;
4220 }
4221
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004222 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004223}
4224
4225
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004226/*
4227Public function, see header qcbor/qcbor_decode.h file
4228*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004229void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4230 const char *szLabel,
4231 uint32_t uConvertTypes,
4232 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004233{
4234 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004235 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4236 szLabel,
4237 uConvertTypes,
4238 pnValue,
4239 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004240
4241 if(pMe->uLastError == QCBOR_SUCCESS) {
4242 // The above conversion succeeded
4243 return;
4244 }
4245
4246 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4247 // The above conversion failed in a way that code below can't correct
4248 return;
4249 }
4250
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004251 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004252}
4253
4254
Laurence Lundblade93d89472020-10-03 22:30:50 -07004255static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004256{
4257 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004258 case QCBOR_TYPE_DOUBLE:
4259 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004260#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004261 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004262 // Can't use llround here because it will not convert values
4263 // greater than INT64_MAX and less than UINT64_MAX that
4264 // need to be converted so it is more complicated.
4265 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4266 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4267 if(isnan(pItem->val.dfnum)) {
4268 return QCBOR_ERR_FLOAT_EXCEPTION;
4269 } else if(pItem->val.dfnum < 0) {
4270 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4271 } else {
4272 double dRounded = round(pItem->val.dfnum);
4273 // See discussion in DecodeDateEpoch() for
4274 // explanation of - 0x7ff
4275 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4276 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4277 }
4278 *puValue = (uint64_t)dRounded;
4279 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004280 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004281 if(isnan(pItem->val.fnum)) {
4282 return QCBOR_ERR_FLOAT_EXCEPTION;
4283 } else if(pItem->val.fnum < 0) {
4284 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4285 } else {
4286 float fRounded = roundf(pItem->val.fnum);
4287 // See discussion in DecodeDateEpoch() for
4288 // explanation of - 0x7ff
4289 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4290 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4291 }
4292 *puValue = (uint64_t)fRounded;
4293 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004294 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004295 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4296 // round() and roundf() shouldn't result in exceptions here, but
4297 // catch them to be robust and thorough. Don't try to
4298 // distinguish between the various exceptions because it seems
4299 // they vary by CPU, compiler and OS.
4300 return QCBOR_ERR_FLOAT_EXCEPTION;
4301 }
4302
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004303 } else {
4304 return QCBOR_ERR_UNEXPECTED_TYPE;
4305 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004306#else
4307 return QCBOR_ERR_HW_FLOAT_DISABLED;
4308#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004309 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004310
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004311 case QCBOR_TYPE_INT64:
4312 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4313 if(pItem->val.int64 >= 0) {
4314 *puValue = (uint64_t)pItem->val.int64;
4315 } else {
4316 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4317 }
4318 } else {
4319 return QCBOR_ERR_UNEXPECTED_TYPE;
4320 }
4321 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004322
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004323 case QCBOR_TYPE_UINT64:
4324 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4325 *puValue = pItem->val.uint64;
4326 } else {
4327 return QCBOR_ERR_UNEXPECTED_TYPE;
4328 }
4329 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004330
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004331 default:
4332 return QCBOR_ERR_UNEXPECTED_TYPE;
4333 }
4334
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004335 return QCBOR_SUCCESS;
4336}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004337
4338
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004339void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004340 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004341 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004342 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004343{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004344 if(pMe->uLastError != QCBOR_SUCCESS) {
4345 return;
4346 }
4347
Laurence Lundbladec4537442020-04-14 18:53:22 -07004348 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004349
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004350 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4351 if(uError) {
4352 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004353 return;
4354 }
4355
Laurence Lundbladea826c502020-05-10 21:07:00 -07004356 if(pItem) {
4357 *pItem = Item;
4358 }
4359
Laurence Lundblade93d89472020-10-03 22:30:50 -07004360 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004361}
4362
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004363
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004364void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004365 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004366 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004367 uint64_t *puValue,
4368 QCBORItem *pItem)
4369{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004370 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004371 if(pMe->uLastError != QCBOR_SUCCESS) {
4372 return;
4373 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004374
Laurence Lundblade93d89472020-10-03 22:30:50 -07004375 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004376}
4377
4378
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004379void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004380 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004381 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004382 uint64_t *puValue,
4383 QCBORItem *pItem)
4384{
4385 if(pMe->uLastError != QCBOR_SUCCESS) {
4386 return;
4387 }
4388
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004389 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004390 if(pMe->uLastError != QCBOR_SUCCESS) {
4391 return;
4392 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004393
Laurence Lundblade93d89472020-10-03 22:30:50 -07004394 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004395}
4396
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004397
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004398
Laurence Lundblade93d89472020-10-03 22:30:50 -07004399static QCBORError
4400UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004401{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004402 switch(pItem->uDataType) {
4403
4404 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004405 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004406 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4407 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004408 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004409 }
4410 break;
4411
4412 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004413 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004414 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4415 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004416 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004417 }
4418 break;
4419
4420#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4421
4422 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004423 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004424 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004425 pItem->val.expAndMantissa.nExponent,
4426 puValue,
4427 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004428 } 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_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004434 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004435 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4436 pItem->val.expAndMantissa.nExponent,
4437 puValue,
4438 Exponentitate2);
4439 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004440 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004441 }
4442 break;
4443
4444 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004445 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004446 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004447 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004448 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004449 if(uErr != QCBOR_SUCCESS) {
4450 return uErr;
4451 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004452 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004453 pItem->val.expAndMantissa.nExponent,
4454 puValue,
4455 Exponentitate10);
4456 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004457 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004458 }
4459 break;
4460
4461 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004462 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004463 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4464 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004465 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004466 }
4467 break;
4468
4469 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004470 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004471 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004472 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004473 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004474 if(uErr != QCBOR_SUCCESS) {
4475 return uErr;
4476 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004477 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004478 pItem->val.expAndMantissa.nExponent,
4479 puValue,
4480 Exponentitate2);
4481 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004482 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004483 }
4484 break;
4485
4486 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004487 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004488 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4489 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004490 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004491 }
4492 break;
4493#endif
4494 default:
4495 return QCBOR_ERR_UNEXPECTED_TYPE;
4496 }
4497}
4498
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004499
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004500/*
4501 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004502 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004503void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004504{
4505 QCBORItem Item;
4506
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004507 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004508
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004509 if(pMe->uLastError == QCBOR_SUCCESS) {
4510 // The above conversion succeeded
4511 return;
4512 }
4513
4514 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4515 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004516 return;
4517 }
4518
Laurence Lundblade93d89472020-10-03 22:30:50 -07004519 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004520}
4521
Laurence Lundbladec4537442020-04-14 18:53:22 -07004522
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004523/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004524 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004525*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004526void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004527 int64_t nLabel,
4528 uint32_t uConvertTypes,
4529 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004530{
4531 QCBORItem Item;
4532
Laurence Lundblade93d89472020-10-03 22:30:50 -07004533 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4534 nLabel,
4535 uConvertTypes,
4536 puValue,
4537 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004538
4539 if(pMe->uLastError == QCBOR_SUCCESS) {
4540 // The above conversion succeeded
4541 return;
4542 }
4543
4544 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4545 // The above conversion failed in a way that code below can't correct
4546 return;
4547 }
4548
Laurence Lundblade93d89472020-10-03 22:30:50 -07004549 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004550}
4551
4552
4553/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004554 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004555*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004556void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004557 const char *szLabel,
4558 uint32_t uConvertTypes,
4559 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004560{
4561 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004562 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4563 szLabel,
4564 uConvertTypes,
4565 puValue,
4566 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004567
4568 if(pMe->uLastError == QCBOR_SUCCESS) {
4569 // The above conversion succeeded
4570 return;
4571 }
4572
4573 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4574 // The above conversion failed in a way that code below can't correct
4575 return;
4576 }
4577
Laurence Lundblade93d89472020-10-03 22:30:50 -07004578 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004579}
4580
4581
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004582
4583
Laurence Lundblade9b334962020-08-27 10:55:53 -07004584static QCBORError ConvertDouble(const QCBORItem *pItem,
4585 uint32_t uConvertTypes,
4586 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004587{
4588 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004589 case QCBOR_TYPE_FLOAT:
4590#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4591 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4592 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004593 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004594 *pdValue = (double)pItem->val.fnum;
4595 } else {
4596 return QCBOR_ERR_UNEXPECTED_TYPE;
4597 }
4598 }
4599#else
4600 return QCBOR_ERR_HW_FLOAT_DISABLED;
4601#endif
4602 break;
4603
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004604 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004605 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4606 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004607 *pdValue = pItem->val.dfnum;
4608 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004609 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004610 }
4611 }
4612 break;
4613
4614 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004615#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004616 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004617 // A simple cast seems to do the job with no worry of exceptions.
4618 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004619 *pdValue = (double)pItem->val.int64;
4620
4621 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004622 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004623 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004624#else
4625 return QCBOR_ERR_HW_FLOAT_DISABLED;
4626#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004627 break;
4628
4629 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004630#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004631 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004632 // A simple cast seems to do the job with no worry of exceptions.
4633 // There will be precision loss for some values.
4634 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004635 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004636 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004637 }
4638 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004639#else
4640 return QCBOR_ERR_HW_FLOAT_DISABLED;
4641#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004642
4643 default:
4644 return QCBOR_ERR_UNEXPECTED_TYPE;
4645 }
4646
4647 return QCBOR_SUCCESS;
4648}
4649
4650
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004651void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004652 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004653 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004654 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004655{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004656 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004657 return;
4658 }
4659
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004660 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004661
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004662 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004663 if(uError) {
4664 pMe->uLastError = (uint8_t)uError;
4665 return;
4666 }
4667
4668 if(pItem) {
4669 *pItem = Item;
4670 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004671
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004672 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004673}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004674
Laurence Lundbladec4537442020-04-14 18:53:22 -07004675
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004676void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4677 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004678 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004679 double *pdValue,
4680 QCBORItem *pItem)
4681{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004682 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004683 if(pMe->uLastError != QCBOR_SUCCESS) {
4684 return;
4685 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004686
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004687 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004688}
4689
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004690
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004691void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4692 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004693 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004694 double *pdValue,
4695 QCBORItem *pItem)
4696{
4697 if(pMe->uLastError != QCBOR_SUCCESS) {
4698 return;
4699 }
4700
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004701 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004702 if(pMe->uLastError != QCBOR_SUCCESS) {
4703 return;
4704 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004705
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004706 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004707}
4708
4709
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004710#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004711static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4712{
4713 double dResult;
4714
4715 dResult = 0.0;
4716 const uint8_t *pByte = BigNum.ptr;
4717 size_t uLen = BigNum.len;
4718 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004719 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004720 while(uLen--) {
4721 dResult = (dResult * 256.0) + (double)*pByte++;
4722 }
4723
4724 return dResult;
4725}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004726#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4727
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004728
Laurence Lundblade93d89472020-10-03 22:30:50 -07004729static QCBORError
4730DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004731{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004732#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004733 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004734 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4735
4736 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004737 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004738
4739#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004740 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004741 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004742 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004743 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4744 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4745 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004746 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004747 }
4748 break;
4749
4750 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004751 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004752 // Underflow gives 0, overflow gives infinity
4753 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4754 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004755 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004756 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004757 }
4758 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004759#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004760
4761 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004762 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004763 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4764 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004765 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004766 }
4767 break;
4768
4769 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004770 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004771 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004772 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004773 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004774 }
4775 break;
4776
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004777#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004778 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004779 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004780 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4781 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4782 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004783 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004784 }
4785 break;
4786
4787 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004788 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004789 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4790 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4791 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004792 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004793 }
4794 break;
4795
4796 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004797 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004798 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4799 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4800 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004801 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004802 }
4803 break;
4804
4805 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004806 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004807 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004808 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4809 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004810 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004811 }
4812 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004813#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4814
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004815 default:
4816 return QCBOR_ERR_UNEXPECTED_TYPE;
4817 }
4818
4819 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004820
4821#else
4822 (void)pItem;
4823 (void)uConvertTypes;
4824 (void)pdValue;
4825 return QCBOR_ERR_HW_FLOAT_DISABLED;
4826#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4827
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004828}
4829
4830
4831/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004832 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004833*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004834void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4835 uint32_t uConvertTypes,
4836 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004837{
4838
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004839 QCBORItem Item;
4840
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004841 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004842
4843 if(pMe->uLastError == QCBOR_SUCCESS) {
4844 // The above conversion succeeded
4845 return;
4846 }
4847
4848 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4849 // The above conversion failed in a way that code below can't correct
4850 return;
4851 }
4852
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004853 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004854}
4855
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004856
4857/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004858 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004859*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004860void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4861 int64_t nLabel,
4862 uint32_t uConvertTypes,
4863 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004864{
4865 QCBORItem Item;
4866
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004867 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004868
4869 if(pMe->uLastError == QCBOR_SUCCESS) {
4870 // The above conversion succeeded
4871 return;
4872 }
4873
4874 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4875 // The above conversion failed in a way that code below can't correct
4876 return;
4877 }
4878
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004879 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004880}
4881
4882
4883/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004884 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004885*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004886void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4887 const char *szLabel,
4888 uint32_t uConvertTypes,
4889 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004890{
4891 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004892 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004893
4894 if(pMe->uLastError == QCBOR_SUCCESS) {
4895 // The above conversion succeeded
4896 return;
4897 }
4898
4899 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4900 // The above conversion failed in a way that code below can't correct
4901 return;
4902 }
4903
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004904 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004905}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004906
4907
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004908
4909
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004910#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004911static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4912{
4913 while((uInt & 0xff00000000000000UL) == 0) {
4914 uInt = uInt << 8;
4915 };
4916
4917 UsefulOutBuf UOB;
4918
4919 UsefulOutBuf_Init(&UOB, Buffer);
4920
4921 while(uInt) {
4922 const uint64_t xx = uInt & 0xff00000000000000UL;
4923 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4924 uInt = uInt << 8;
4925 (void)xx;
4926 }
4927
4928 return UsefulOutBuf_OutUBuf(&UOB);
4929}
4930
4931
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004932static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4933 TagSpecification TagSpec,
4934 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004935{
4936 QCBORError uErr;
4937 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004938 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004939 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004940 if(uErr != QCBOR_SUCCESS) {
4941 goto Done;
4942 }
4943
4944 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4945 break; // Successful exit. Moving on to finish decoding.
4946 }
4947
4948 // The item is an array, which means an undecoded
4949 // mantissa and exponent, so decode it. It will then
4950 // have a different type and exit the loop if.
4951 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4952 if(uErr != QCBOR_SUCCESS) {
4953 goto Done;
4954 }
4955
4956 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07004957 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004958 }
4959Done:
4960 return uErr;
4961}
4962
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004963
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004964static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004965 TagSpecification TagSpec,
4966 QCBORItem *pItem,
4967 int64_t *pnMantissa,
4968 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004969{
4970 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004971
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004972 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004973 if(uErr != QCBOR_SUCCESS) {
4974 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004975 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004976
Laurence Lundblade9b334962020-08-27 10:55:53 -07004977 switch (pItem->uDataType) {
4978
4979 case QCBOR_TYPE_DECIMAL_FRACTION:
4980 case QCBOR_TYPE_BIGFLOAT:
4981 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4982 *pnExponent = pItem->val.expAndMantissa.nExponent;
4983 break;
4984
4985 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4986 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4987 *pnExponent = pItem->val.expAndMantissa.nExponent;
4988 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4989 break;
4990
4991 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4992 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4993 *pnExponent = pItem->val.expAndMantissa.nExponent;
4994 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4995 break;
4996
4997 default:
4998 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
4999 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005000
5001 Done:
5002 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005003}
5004
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005005
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005006static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005007 TagSpecification TagSpec,
5008 QCBORItem *pItem,
5009 UsefulBuf BufferForMantissa,
5010 UsefulBufC *pMantissa,
5011 bool *pbIsNegative,
5012 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005013{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005014 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005015
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005016 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005017 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005018 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005019 }
5020
5021 uint64_t uMantissa;
5022
5023 switch (pItem->uDataType) {
5024
5025 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005026 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005027 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5028 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5029 *pbIsNegative = false;
5030 } else {
5031 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5032 *pbIsNegative = true;
5033 }
5034 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5035 *pnExponent = pItem->val.expAndMantissa.nExponent;
5036 break;
5037
5038 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005039 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005040 *pnExponent = pItem->val.expAndMantissa.nExponent;
5041 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5042 *pbIsNegative = false;
5043 break;
5044
5045 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005046 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005047 *pnExponent = pItem->val.expAndMantissa.nExponent;
5048 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5049 *pbIsNegative = true;
5050 break;
5051
5052 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005053 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005054 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005055
5056Done:
5057 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005058}
5059
5060
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005061/*
5062 Public function, see header qcbor/qcbor_decode.h file
5063*/
5064void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5065 uint8_t uTagRequirement,
5066 int64_t *pnMantissa,
5067 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005068{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005069 if(pMe->uLastError != QCBOR_SUCCESS) {
5070 return;
5071 }
5072
5073 QCBORItem Item;
5074 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5075 if(uError) {
5076 pMe->uLastError = (uint8_t)uError;
5077 return;
5078 }
5079
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005080 const TagSpecification TagSpec =
5081 {
5082 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005083 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5084 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5085 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005086 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005087
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005088 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005089}
5090
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005091
5092/*
5093 Public function, see header qcbor/qcbor_decode.h file
5094*/
5095void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005096 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005097 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005098 int64_t *pnMantissa,
5099 int64_t *pnExponent)
5100{
5101 if(pMe->uLastError != QCBOR_SUCCESS) {
5102 return;
5103 }
5104
5105 QCBORItem Item;
5106 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5107
5108 const TagSpecification TagSpec =
5109 {
5110 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005111 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5112 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5113 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005114 };
5115
5116 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5117}
5118
5119
5120/*
5121 Public function, see header qcbor/qcbor_decode.h file
5122*/
5123void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005124 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005125 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005126 int64_t *pnMantissa,
5127 int64_t *pnExponent)
5128{
5129 if(pMe->uLastError != QCBOR_SUCCESS) {
5130 return;
5131 }
5132
5133 QCBORItem Item;
5134 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5135
5136 const TagSpecification TagSpec =
5137 {
5138 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005139 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5140 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5141 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005142 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005143
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005144 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5145}
5146
5147
5148/*
5149 Public function, see header qcbor/qcbor_decode.h file
5150*/
5151void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5152 uint8_t uTagRequirement,
5153 UsefulBuf MantissaBuffer,
5154 UsefulBufC *pMantissa,
5155 bool *pbMantissaIsNegative,
5156 int64_t *pnExponent)
5157{
5158 if(pMe->uLastError != QCBOR_SUCCESS) {
5159 return;
5160 }
5161
5162 QCBORItem Item;
5163 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5164 if(uError) {
5165 pMe->uLastError = (uint8_t)uError;
5166 return;
5167 }
5168
5169 const TagSpecification TagSpec =
5170 {
5171 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005172 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5173 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5174 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005175 };
5176
Laurence Lundblade93d89472020-10-03 22:30:50 -07005177 ProcessMantissaAndExponentBig(pMe,
5178 TagSpec,
5179 &Item,
5180 MantissaBuffer,
5181 pMantissa,
5182 pbMantissaIsNegative,
5183 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005184}
5185
5186
5187/*
5188 Public function, see header qcbor/qcbor_decode.h file
5189*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005190void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005191 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005192 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005193 UsefulBuf BufferForMantissa,
5194 UsefulBufC *pMantissa,
5195 bool *pbIsNegative,
5196 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005197{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005198 if(pMe->uLastError != QCBOR_SUCCESS) {
5199 return;
5200 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005201
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005202 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005203 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005204 if(pMe->uLastError != QCBOR_SUCCESS) {
5205 return;
5206 }
5207
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005208 const TagSpecification TagSpec =
5209 {
5210 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005211 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5212 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5213 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005214 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005215
Laurence Lundblade93d89472020-10-03 22:30:50 -07005216 ProcessMantissaAndExponentBig(pMe,
5217 TagSpec,
5218 &Item,
5219 BufferForMantissa,
5220 pMantissa,
5221 pbIsNegative,
5222 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005223}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005224
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005225
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005226/*
5227 Public function, see header qcbor/qcbor_decode.h file
5228*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005229void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005230 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005231 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005232 UsefulBuf BufferForMantissa,
5233 UsefulBufC *pMantissa,
5234 bool *pbIsNegative,
5235 int64_t *pnExponent)
5236{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005237 if(pMe->uLastError != QCBOR_SUCCESS) {
5238 return;
5239 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005240
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005241 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005242 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5243 if(pMe->uLastError != QCBOR_SUCCESS) {
5244 return;
5245 }
5246
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005247 const TagSpecification TagSpec =
5248 {
5249 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005250 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5251 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5252 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005253 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005254
5255 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5256}
5257
5258
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005259/*
5260 Public function, see header qcbor/qcbor_decode.h file
5261*/
5262void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5263 uint8_t uTagRequirement,
5264 int64_t *pnMantissa,
5265 int64_t *pnExponent)
5266{
5267 if(pMe->uLastError != QCBOR_SUCCESS) {
5268 return;
5269 }
5270
5271 QCBORItem Item;
5272 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5273 if(uError) {
5274 pMe->uLastError = (uint8_t)uError;
5275 return;
5276 }
5277 const TagSpecification TagSpec =
5278 {
5279 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005280 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5281 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5282 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005283 };
5284
5285 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5286}
5287
5288
5289/*
5290 Public function, see header qcbor/qcbor_decode.h file
5291*/
5292void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005293 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005294 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005295 int64_t *pnMantissa,
5296 int64_t *pnExponent)
5297{
5298 if(pMe->uLastError != QCBOR_SUCCESS) {
5299 return;
5300 }
5301
5302 QCBORItem Item;
5303 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5304 if(pMe->uLastError != QCBOR_SUCCESS) {
5305 return;
5306 }
5307
5308 const TagSpecification TagSpec =
5309 {
5310 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005311 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5312 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5313 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005314 };
5315
5316 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5317}
5318
5319
5320/*
5321 Public function, see header qcbor/qcbor_decode.h file
5322*/
5323void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005324 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005325 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005326 int64_t *pnMantissa,
5327 int64_t *pnExponent)
5328{
5329 if(pMe->uLastError != QCBOR_SUCCESS) {
5330 return;
5331 }
5332
5333 QCBORItem Item;
5334 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5335 if(pMe->uLastError != QCBOR_SUCCESS) {
5336 return;
5337 }
5338
5339 const TagSpecification TagSpec =
5340 {
5341 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005342 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5343 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5344 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005345 };
5346
5347 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5348}
5349
5350
5351/*
5352 Public function, see header qcbor/qcbor_decode.h file
5353*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005354void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5355 uint8_t uTagRequirement,
5356 UsefulBuf MantissaBuffer,
5357 UsefulBufC *pMantissa,
5358 bool *pbMantissaIsNegative,
5359 int64_t *pnExponent)
5360{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005361 if(pMe->uLastError != QCBOR_SUCCESS) {
5362 return;
5363 }
5364
5365 QCBORItem Item;
5366 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5367 if(uError) {
5368 pMe->uLastError = (uint8_t)uError;
5369 return;
5370 }
5371
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005372 const TagSpecification TagSpec =
5373 {
5374 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005375 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5376 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5377 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005378 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005379
5380 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005381}
5382
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005383
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005384/*
5385 Public function, see header qcbor/qcbor_decode.h file
5386*/
5387void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005388 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005389 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005390 UsefulBuf BufferForMantissa,
5391 UsefulBufC *pMantissa,
5392 bool *pbIsNegative,
5393 int64_t *pnExponent)
5394{
5395 if(pMe->uLastError != QCBOR_SUCCESS) {
5396 return;
5397 }
5398
5399 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005400 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5401 if(pMe->uLastError != QCBOR_SUCCESS) {
5402 return;
5403 }
5404
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005405 const TagSpecification TagSpec =
5406 {
5407 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005408 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5409 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5410 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005411 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005412
Laurence Lundblade93d89472020-10-03 22:30:50 -07005413 ProcessMantissaAndExponentBig(pMe,
5414 TagSpec,
5415 &Item,
5416 BufferForMantissa,
5417 pMantissa,
5418 pbIsNegative,
5419 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005420}
5421
5422
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005423/*
5424 Public function, see header qcbor/qcbor_decode.h file
5425*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005426void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005427 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005428 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005429 UsefulBuf BufferForMantissa,
5430 UsefulBufC *pMantissa,
5431 bool *pbIsNegative,
5432 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005433{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005434 if(pMe->uLastError != QCBOR_SUCCESS) {
5435 return;
5436 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005437
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005438 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005439 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5440 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005441 return;
5442 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005443
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005444 const TagSpecification TagSpec =
5445 {
5446 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005447 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5448 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5449 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005450 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005451
Laurence Lundblade93d89472020-10-03 22:30:50 -07005452 ProcessMantissaAndExponentBig(pMe,
5453 TagSpec,
5454 &Item,
5455 BufferForMantissa,
5456 pMantissa,
5457 pbIsNegative,
5458 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005459}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005460
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005461#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */