blob: 3e36e5abcea039052555937902a3507936a1bdac [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 Lundblade9b334962020-08-27 10:55:53 -07002196 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2197 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002198 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002199 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002200 }
2201}
2202
Laurence Lundblade9b334962020-08-27 10:55:53 -07002203/*
2204 Public function, see header qcbor/qcbor_decode.h file
2205*/
2206uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2207 uint32_t uIndex)
2208{
2209 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2210 return CBOR_TAG_INVALID64;
2211 } else {
2212 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2213 }
2214}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002215
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002216/*
2217
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002218Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002219
Laurence Lundbladeee851742020-01-08 08:37:05 -08002220 - Hit end of input before it was expected while decoding type and
2221 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002222
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002223 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002224
Laurence Lundbladeee851742020-01-08 08:37:05 -08002225 - Hit end of input while decoding a text or byte string
2226 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002227
Laurence Lundbladeee851742020-01-08 08:37:05 -08002228 - Encountered conflicting tags -- e.g., an item is tagged both a date
2229 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002230
Laurence Lundbladeee851742020-01-08 08:37:05 -08002231 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002232 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002233
Laurence Lundbladeee851742020-01-08 08:37:05 -08002234 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002235 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002236
Laurence Lundbladeee851742020-01-08 08:37:05 -08002237 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2238 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002239
Laurence Lundbladeee851742020-01-08 08:37:05 -08002240 - The type of a map label is not a string or int
2241 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002242
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002243 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002244
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002245 */
2246
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002247
2248
Laurence Lundbladef6531662018-12-04 10:42:22 +09002249
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002250/* ===========================================================================
2251 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002252
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002253 This implements a simple sting allocator for indefinite length
2254 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2255 implements the function type QCBORStringAllocate and allows easy
2256 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002257
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002258 This particular allocator is built-in for convenience. The caller
2259 can implement their own. All of this following code will get
2260 dead-stripped if QCBORDecode_SetMemPool() is not called.
2261
2262 This is a very primitive memory allocator. It does not track
2263 individual allocations, only a high-water mark. A free or
2264 reallocation must be of the last chunk allocated.
2265
2266 The size of the pool and offset to free memory are packed into the
2267 first 8 bytes of the memory pool so we don't have to keep them in
2268 the decode context. Since the address of the pool may not be
2269 aligned, they have to be packed and unpacked as if they were
2270 serialized data of the wire or such.
2271
2272 The sizes packed in are uint32_t to be the same on all CPU types
2273 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002274 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002275
2276
Laurence Lundbladeee851742020-01-08 08:37:05 -08002277static inline int
2278MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002279{
2280 // Use of UsefulInputBuf is overkill, but it is convenient.
2281 UsefulInputBuf UIB;
2282
Laurence Lundbladeee851742020-01-08 08:37:05 -08002283 // Just assume the size here. It was checked during SetUp so
2284 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002285 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002286 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2287 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2288 return UsefulInputBuf_GetError(&UIB);
2289}
2290
2291
Laurence Lundbladeee851742020-01-08 08:37:05 -08002292static inline int
2293MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002294{
2295 // Use of UsefulOutBuf is overkill, but convenient. The
2296 // length check performed here is useful.
2297 UsefulOutBuf UOB;
2298
2299 UsefulOutBuf_Init(&UOB, Pool);
2300 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2301 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2302 return UsefulOutBuf_GetError(&UOB);
2303}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002304
2305
2306/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002307 Internal function for an allocation, reallocation free and destuct.
2308
2309 Having only one function rather than one each per mode saves space in
2310 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002311
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002312 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2313 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002314static UsefulBuf
2315MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002316{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002317 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002318
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002319 uint32_t uPoolSize;
2320 uint32_t uFreeOffset;
2321
2322 if(uNewSize > UINT32_MAX) {
2323 // This allocator is only good up to 4GB. This check should
2324 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2325 goto Done;
2326 }
2327 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2328
2329 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2330 goto Done;
2331 }
2332
2333 if(uNewSize) {
2334 if(pMem) {
2335 // REALLOCATION MODE
2336 // Calculate pointer to the end of the memory pool. It is
2337 // assumed that pPool + uPoolSize won't wrap around by
2338 // assuming the caller won't pass a pool buffer in that is
2339 // not in legitimate memory space.
2340 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2341
2342 // Check that the pointer for reallocation is in the range of the
2343 // pool. This also makes sure that pointer math further down
2344 // doesn't wrap under or over.
2345 if(pMem >= pPool && pMem < pPoolEnd) {
2346 // Offset to start of chunk for reallocation. This won't
2347 // wrap under because of check that pMem >= pPool. Cast
2348 // is safe because the pool is always less than UINT32_MAX
2349 // because of check in QCBORDecode_SetMemPool().
2350 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2351
2352 // Check to see if the allocation will fit. uPoolSize -
2353 // uMemOffset will not wrap under because of check that
2354 // pMem is in the range of the uPoolSize by check above.
2355 if(uNewSize <= uPoolSize - uMemOffset) {
2356 ReturnValue.ptr = pMem;
2357 ReturnValue.len = uNewSize;
2358
2359 // Addition won't wrap around over because uNewSize was
2360 // checked to be sure it is less than the pool size.
2361 uFreeOffset = uMemOffset + uNewSize32;
2362 }
2363 }
2364 } else {
2365 // ALLOCATION MODE
2366 // uPoolSize - uFreeOffset will not underflow because this
2367 // pool implementation makes sure uFreeOffset is always
2368 // smaller than uPoolSize through this check here and
2369 // reallocation case.
2370 if(uNewSize <= uPoolSize - uFreeOffset) {
2371 ReturnValue.len = uNewSize;
2372 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002373 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002374 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002375 }
2376 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002377 if(pMem) {
2378 // FREE MODE
2379 // Cast is safe because of limit on pool size in
2380 // QCBORDecode_SetMemPool()
2381 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2382 } else {
2383 // DESTRUCT MODE
2384 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002385 }
2386 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002387
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002388 UsefulBuf Pool = {pPool, uPoolSize};
2389 MemPool_Pack(Pool, uFreeOffset);
2390
2391Done:
2392 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002393}
2394
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002395
Laurence Lundbladef6531662018-12-04 10:42:22 +09002396/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002397 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002398 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002399QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2400 UsefulBuf Pool,
2401 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002402{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002403 // The pool size and free mem offset are packed into the beginning
2404 // of the pool memory. This compile time check make sure the
2405 // constant in the header is correct. This check should optimize
2406 // down to nothing.
2407 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002408 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002409 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002410
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002411 // The pool size and free offset packed in to the beginning of pool
2412 // memory are only 32-bits. This check will optimize out on 32-bit
2413 // machines.
2414 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002415 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002416 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002417
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002418 // This checks that the pool buffer given is big enough.
2419 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002420 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002421 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002422
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002423 pMe->StringAllocator.pfAllocator = MemPool_Function;
2424 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2425 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002426
Laurence Lundblade30816f22018-11-10 13:40:22 +07002427 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002428}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002429
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002430
2431
Laurence Lundblade9b334962020-08-27 10:55:53 -07002432static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2433{
2434 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2435}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002436
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002437
2438/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002439 Consume an entire map or array (and do next to
2440 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002441 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002442static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002443ConsumeItem(QCBORDecodeContext *pMe,
2444 const QCBORItem *pItemToConsume,
2445 uint_fast8_t *puNextNestLevel)
2446{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002447 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002448 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002449
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002450 // If it is a map or array, this will tell if it is empty.
2451 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2452
2453 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2454 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002455
Laurence Lundblade1341c592020-04-11 14:19:05 -07002456 /* This works for definite and indefinite length
2457 * maps and arrays by using the nesting level
2458 */
2459 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002460 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002461 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002462 goto Done;
2463 }
2464 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002465
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002466 *puNextNestLevel = Item.uNextNestLevel;
2467
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002468 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002469
Laurence Lundblade1341c592020-04-11 14:19:05 -07002470 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002471 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002472 /* Just pass the nesting level through */
2473 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2474
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002475 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002476 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002477
2478Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002479 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002480}
2481
2482
Laurence Lundblade1341c592020-04-11 14:19:05 -07002483/* Return true if the labels in Item1 and Item2 are the same.
2484 Works only for integer and string labels. Returns false
2485 for any other type. */
2486static inline bool
2487MatchLabel(QCBORItem Item1, QCBORItem Item2)
2488{
2489 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2490 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2491 return true;
2492 }
2493 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002494 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002495 return true;
2496 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002497 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002498 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2499 return true;
2500 }
2501 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2502 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2503 return true;
2504 }
2505 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002506
Laurence Lundblade1341c592020-04-11 14:19:05 -07002507 /* Other label types are never matched */
2508 return false;
2509}
2510
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002511
2512/*
2513 Returns true if Item1 and Item2 are the same type
2514 or if either are of QCBOR_TYPE_ANY.
2515 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002516static inline bool
2517MatchType(QCBORItem Item1, QCBORItem Item2)
2518{
2519 if(Item1.uDataType == Item2.uDataType) {
2520 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002521 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002522 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002523 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002524 return true;
2525 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002526 return false;
2527}
2528
2529
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002530/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002531 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002532
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002533 @param[in] pMe The decode context to search.
2534 @param[in,out] pItemArray The items to search for and the items found.
2535 @param[out] puOffset Byte offset of last item matched.
2536 @param[in] pCBContext Context for the not-found item call back.
2537 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002538
2539 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2540
Laurence Lundblade93d89472020-10-03 22:30:50 -07002541 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2542 were found for one of the labels being
2543 search for. This duplicate detection is
2544 only performed for items in pItemArray,
2545 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002546
Laurence Lundblade93d89472020-10-03 22:30:50 -07002547 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2548 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002549
2550 @retval Also errors returned by QCBORDecode_GetNext().
2551
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002552 On input pItemArray contains a list of labels and data types
2553 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002554
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002555 On output the fully retrieved items are filled in with
2556 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002557
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002558 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002559
2560 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002561 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002562static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002563MapSearch(QCBORDecodeContext *pMe,
2564 QCBORItem *pItemArray,
2565 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002566 void *pCBContext,
2567 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002568{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002569 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002570 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002571
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002572 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002573 uReturn = pMe->uLastError;
2574 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002575 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002576
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002577 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002578 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2579 /* QCBOR_TYPE_NONE as first item indicates just looking
2580 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002581 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2582 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002583 }
2584
Laurence Lundblade085d7952020-07-24 10:26:30 -07002585 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2586 // It is an empty bounded array or map
2587 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2588 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002589 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002590 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002591 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002592 // Nothing is ever found in an empty array or map. All items
2593 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002594 uReturn = QCBOR_SUCCESS;
2595 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002596 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002597 }
2598
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002599 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002600 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2601
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002602 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002603 UsefulInputBuf_Seek(&(pMe->InBuf),
2604 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002605
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002606 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002607 Loop over all the items in the map or array. Each item
2608 could be a map or array, but label matching is only at
2609 the main level. This handles definite and indefinite
2610 length maps and arrays. The only reason this is ever
2611 called on arrays is to find their end position.
2612
2613 This will always run over all items in order to do
2614 duplicate detection.
2615
2616 This will exit with failure if it encounters an
2617 unrecoverable error, but continue on for recoverable
2618 errors.
2619
2620 If a recoverable error occurs on a matched item, then
2621 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002622 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002623 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002624 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002625 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002626 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002627 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002628
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002629 /* Get the item */
2630 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002631 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2632 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002633 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002634 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002635 goto Done;
2636 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002637 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002638 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002639 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002640 goto Done;
2641 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002642
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002643 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002644 bool bMatched = false;
2645 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2646 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002647 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002648 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2649 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002650 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002651 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002652 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002653 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002654 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002655 goto Done;
2656 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002657
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002658 if(uResult != QCBOR_SUCCESS) {
2659 uReturn = uResult;
2660 goto Done;
2661 }
2662
Laurence Lundblade1341c592020-04-11 14:19:05 -07002663 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002664 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002665 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002666 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002667 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002668 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002669 bMatched = true;
2670 }
2671 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002672
2673
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002674 if(!bMatched && pfCallback != NULL) {
2675 /*
2676 Call the callback on unmatched labels.
2677 (It is tempting to do duplicate detection here, but that would
2678 require dynamic memory allocation because the number of labels
2679 that might be encountered is unbounded.)
2680 */
2681 uReturn = (*pfCallback)(pCBContext, &Item);
2682 if(uReturn != QCBOR_SUCCESS) {
2683 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002684 }
2685 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002686
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002687 /*
2688 Consume the item whether matched or not. This
2689 does the work of traversing maps and array and
2690 everything in them. In this loop only the
2691 items at the current nesting level are examined
2692 to match the labels.
2693 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002694 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002695 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002696 goto Done;
2697 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002698
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002699 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002700
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002701 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002702
2703 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002704
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002705 // Check here makes sure that this won't accidentally be
2706 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002707 // QCBOR_MAX_DECODE_INPUT_SIZE.
2708 if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
2709 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2710 goto Done;
2711 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002712 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2713 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002714
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002715 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002716 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2717
2718 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002719 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002720 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002721 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002722 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2723 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002724 }
2725 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002726
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002727 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002728}
2729
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002730
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002731/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002732 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002733*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002734void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2735 int64_t nLabel,
2736 uint8_t uQcborType,
2737 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002738{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002739 if(pMe->uLastError != QCBOR_SUCCESS) {
2740 return;
2741 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002742
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002743 QCBORItem OneItemSeach[2];
2744 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2745 OneItemSeach[0].label.int64 = nLabel;
2746 OneItemSeach[0].uDataType = uQcborType;
2747 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002748
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002749 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002750
2751 *pItem = OneItemSeach[0];
2752
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002753 if(uReturn != QCBOR_SUCCESS) {
2754 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002755 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002756 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002757 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002758 }
2759
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002760 Done:
2761 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002762}
2763
2764
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002765/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002766 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002767*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002768void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2769 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002770 uint8_t uQcborType,
2771 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002772{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002773 if(pMe->uLastError != QCBOR_SUCCESS) {
2774 return;
2775 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002776
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002777 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002778 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2779 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2780 OneItemSeach[0].uDataType = uQcborType;
2781 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002782
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002783 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2784 if(uReturn != QCBOR_SUCCESS) {
2785 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002786 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002787 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002788 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002789 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002790 }
2791
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002792 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002793
2794Done:
2795 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002796}
2797
2798
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002799
Laurence Lundblade93d89472020-10-03 22:30:50 -07002800static QCBORError
2801CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002802{
2803 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2804 if(uDataType == puTypeList[i]) {
2805 return QCBOR_SUCCESS;
2806 }
2807 }
2808 return QCBOR_ERR_UNEXPECTED_TYPE;
2809}
2810
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002811
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002812/**
2813 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002814 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002815
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002816 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2817 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002818
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002819 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2820 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002821 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002822static QCBORError
2823CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002824{
2825 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2826 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2827 /* There are tags that QCBOR couldn't process on this item and
2828 the caller has told us there should not be. */
2829 return QCBOR_ERR_UNEXPECTED_TYPE;
2830 }
2831
2832 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2833 const int nItemType = pItem->uDataType;
2834
2835 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2836 // Must match the tag and only the tag
2837 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2838 }
2839
2840 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2841 if(uReturn == QCBOR_SUCCESS) {
2842 return QCBOR_SUCCESS;
2843 }
2844
2845 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2846 /* Must match the content type and only the content type.
2847 There was no match just above so it is a fail. */
2848 return QCBOR_ERR_UNEXPECTED_TYPE;
2849 }
2850
2851 /* If here it can match either the tag or the content
2852 and it hasn't matched the content, so the end
2853 result is whether it matches the tag. This is
2854 also the case that the CBOR standard discourages. */
2855
2856 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2857}
2858
Laurence Lundblade9b334962020-08-27 10:55:53 -07002859
Laurence Lundblade9b334962020-08-27 10:55:53 -07002860
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002861// This could be semi-private if need be
2862static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002863void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2864 int64_t nLabel,
2865 TagSpecification TagSpec,
2866 QCBORItem *pItem)
2867{
2868 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2869 if(pMe->uLastError != QCBOR_SUCCESS) {
2870 return;
2871 }
2872
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002873 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002874}
2875
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002876
2877// This could be semi-private if need be
2878static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002879void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2880 const char *szLabel,
2881 TagSpecification TagSpec,
2882 QCBORItem *pItem)
2883{
2884 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2885 if(pMe->uLastError != QCBOR_SUCCESS) {
2886 return;
2887 }
2888
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002889 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002890}
2891
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002892// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002893void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2894 int64_t nLabel,
2895 TagSpecification TagSpec,
2896 UsefulBufC *pString)
2897{
2898 QCBORItem Item;
2899 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2900 if(pMe->uLastError == QCBOR_SUCCESS) {
2901 *pString = Item.val.string;
2902 }
2903}
2904
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002905// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002906void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2907 const char * szLabel,
2908 TagSpecification TagSpec,
2909 UsefulBufC *pString)
2910{
2911 QCBORItem Item;
2912 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2913 if(pMe->uLastError == QCBOR_SUCCESS) {
2914 *pString = Item.val.string;
2915 }
2916}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002917
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002918/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002919 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002920*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002921void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002922{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002923 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2924 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002925}
2926
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002927/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002928 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002929*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002930void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2931 QCBORItem *pItemList,
2932 void *pCallbackCtx,
2933 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002934{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002935 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2936 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002937}
2938
2939
Laurence Lundblade34691b92020-05-18 22:25:25 -07002940static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002941{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002942 // The first item in pSearch is the one that is to be
2943 // entered. It should be the only one filled in. Any other
2944 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07002945 if(pMe->uLastError != QCBOR_SUCCESS) {
2946 // Already in error state; do nothing.
2947 return;
2948 }
2949
2950 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002951 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002952 if(pMe->uLastError != QCBOR_SUCCESS) {
2953 return;
2954 }
2955
Laurence Lundblade9b334962020-08-27 10:55:53 -07002956 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002957 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002958 return;
2959 }
2960
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002961 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002962 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002963
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002964 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002965 be at the right place.
2966
2967 The UsefulInBuf offset could be anywhere, so no assumption is
2968 made about it.
2969
2970 No assumption is made about the pre-order nesting level either.
2971
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002972 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002973 the map level that is being entered.
2974 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002975 /* Seek to the data item that is the map or array */
2976 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002977
2978 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002979
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07002980 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002981}
2982
2983
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002984/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002985 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002986*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002987void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002988{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002989 QCBORItem OneItemSeach[2];
2990 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2991 OneItemSeach[0].label.int64 = nLabel;
2992 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2993 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002994
Laurence Lundblade9b334962020-08-27 10:55:53 -07002995 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002996 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002997}
2998
2999
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003000/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003001 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003002*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003003void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003004{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003005 QCBORItem OneItemSeach[2];
3006 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3007 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3008 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3009 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003010
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003011 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003012}
3013
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003014/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003015 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003016*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003017void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003018{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003019 QCBORItem OneItemSeach[2];
3020 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3021 OneItemSeach[0].label.int64 = nLabel;
3022 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3023 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003024
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003025 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003026}
3027
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003028/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003029 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003030*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003031void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3032{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003033 QCBORItem OneItemSeach[2];
3034 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3035 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3036 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3037 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003038
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003039 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003040}
3041
3042
Laurence Lundblade02625d42020-06-25 14:41:41 -07003043// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003044void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003045{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003046 QCBORError uErr;
3047
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003048 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003049 if(pMe->uLastError != QCBOR_SUCCESS) {
3050 // Already in error state; do nothing.
3051 return;
3052 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003053
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003054 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003055 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003056 uErr = QCBORDecode_GetNext(pMe, &Item);
3057 if(uErr != QCBOR_SUCCESS) {
3058 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003059 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003060 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003061 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3062 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003063 }
3064
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003065 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003066
3067
Laurence Lundbladef0499502020-08-01 11:55:57 -07003068 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003069 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003070 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3071 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003072 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003073 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3074 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003075 // Special case to increment nesting level for zero-length maps
3076 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003077 DecodeNesting_Descend(&(pMe->nesting), uType);
3078 }
3079
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003080 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003081
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003082 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3083 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003084
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003085 if(pItem != NULL) {
3086 *pItem = Item;
3087 }
3088
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003089Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003090 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003091}
3092
Laurence Lundblade02625d42020-06-25 14:41:41 -07003093
3094/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003095 This is the common work for exiting a level that is a bounded map,
3096 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003097
3098 One chunk of work is to set up the pre-order traversal so it is at
3099 the item just after the bounded map, array or bstr that is being
3100 exited. This is somewhat complex.
3101
3102 The other work is to level-up the bounded mode to next higest bounded
3103 mode or the top level if there isn't one.
3104 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003105static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003106ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003107{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003108 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003109
Laurence Lundblade02625d42020-06-25 14:41:41 -07003110 /*
3111 First the pre-order-traversal byte offset is positioned to the
3112 item just after the bounded mode item that was just consumed.
3113 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003114 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3115
Laurence Lundblade02625d42020-06-25 14:41:41 -07003116 /*
3117 Next, set the current nesting level to one above the bounded level
3118 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003119
Laurence Lundblade02625d42020-06-25 14:41:41 -07003120 DecodeNesting_CheckBoundedType() is always called before this and
3121 makes sure pCurrentBounded is valid.
3122 */
3123 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3124
3125 /*
3126 This does the complex work of leveling up the pre-order traversal
3127 when the end of a map or array or another bounded level is
3128 reached. It may do nothing, or ascend all the way to the top
3129 level.
3130 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003131 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003132 if(uErr != QCBOR_SUCCESS) {
3133 goto Done;
3134 }
3135
Laurence Lundblade02625d42020-06-25 14:41:41 -07003136 /*
3137 This makes the next highest bounded level the current bounded
3138 level. If there is no next highest level, then no bounded mode is
3139 in effect.
3140 */
3141 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003142
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003143 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003144
3145Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003146 return uErr;
3147}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003148
Laurence Lundblade02625d42020-06-25 14:41:41 -07003149
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003150// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003151void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003152{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003153 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003154 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003155 return;
3156 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003157
Laurence Lundblade02625d42020-06-25 14:41:41 -07003158 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003159
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003160 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003161 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003162 goto Done;
3163 }
3164
Laurence Lundblade02625d42020-06-25 14:41:41 -07003165 /*
3166 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003167 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003168 from previous map search, then do a dummy search.
3169 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003170 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003171 QCBORItem Dummy;
3172 Dummy.uLabelType = QCBOR_TYPE_NONE;
3173 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3174 if(uErr != QCBOR_SUCCESS) {
3175 goto Done;
3176 }
3177 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003178
Laurence Lundblade02625d42020-06-25 14:41:41 -07003179 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003180
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003181Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003182 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003183}
3184
3185
Laurence Lundblade1341c592020-04-11 14:19:05 -07003186
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003187static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003188 const QCBORItem *pItem,
3189 uint8_t uTagRequirement,
3190 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003191{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003192 if(pBstr) {
3193 *pBstr = NULLUsefulBufC;
3194 }
3195
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003196 if(pMe->uLastError != QCBOR_SUCCESS) {
3197 // Already in error state; do nothing.
3198 return pMe->uLastError;
3199 }
3200
3201 QCBORError uError = QCBOR_SUCCESS;
3202
3203 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3204 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3205 goto Done;;
3206 }
3207
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003208 const TagSpecification TagSpec =
3209 {
3210 uTagRequirement,
3211 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3212 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3213 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003214
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003215 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003216 if(uError != QCBOR_SUCCESS) {
3217 goto Done;
3218 }
3219
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003220 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003221 // Reverse the decrement done by GetNext() for the bstr so the
3222 // increment in NestLevelAscender() called by ExitBoundedLevel()
3223 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003224 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003225 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003226
3227 if(pBstr) {
3228 *pBstr = pItem->val.string;
3229 }
3230
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003231 // This saves the current length of the UsefulInputBuf and then
3232 // narrows the UsefulInputBuf to start and length of the wrapped
3233 // CBOR that is being entered.
3234 //
3235 // This makes sure the length is less than
3236 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3237 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3238 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3239 // the casts safe. uEndOfBstr will always be less than
3240 // uPreviousLength because of the way UsefulInputBuf works so there
3241 // is no need to check it. There is also a range check in the
3242 // seek.
3243 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003244 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003245 // amount to much code.
3246 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3247 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003248 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003249 goto Done;
3250 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003251 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003252 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003253 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003254
Laurence Lundblade02625d42020-06-25 14:41:41 -07003255 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003256 (uint32_t)uPreviousLength,
3257 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003258Done:
3259 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003260}
3261
3262
Laurence Lundblade02625d42020-06-25 14:41:41 -07003263/*
3264 Public function, see header qcbor/qcbor_decode.h file
3265 */
3266void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003267 uint8_t uTagRequirement,
3268 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003269{
3270 if(pMe->uLastError != QCBOR_SUCCESS) {
3271 // Already in error state; do nothing.
3272 return;
3273 }
3274
3275 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003276 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003277 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3278 if(pMe->uLastError != QCBOR_SUCCESS) {
3279 return;
3280 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003281
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003282 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003283 &Item,
3284 uTagRequirement,
3285 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003286}
3287
3288
Laurence Lundblade02625d42020-06-25 14:41:41 -07003289/*
3290 Public function, see header qcbor/qcbor_decode.h file
3291 */
3292void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003293 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003294 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003295 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003296{
3297 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003298 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003299
Laurence Lundblade93d89472020-10-03 22:30:50 -07003300 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3301 &Item,
3302 uTagRequirement,
3303 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003304}
3305
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003306
Laurence Lundblade02625d42020-06-25 14:41:41 -07003307/*
3308 Public function, see header qcbor/qcbor_decode.h file
3309 */
3310void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003311 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003312 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003313 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003314{
3315 QCBORItem Item;
3316 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3317
Laurence Lundblade93d89472020-10-03 22:30:50 -07003318 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3319 &Item,
3320 uTagRequirement,
3321 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003322}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003323
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003324
Laurence Lundblade02625d42020-06-25 14:41:41 -07003325/*
3326 Public function, see header qcbor/qcbor_decode.h file
3327 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003328void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003329{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003330 if(pMe->uLastError != QCBOR_SUCCESS) {
3331 // Already in error state; do nothing.
3332 return;
3333 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003334
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003335 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003336 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003337 return;
3338 }
3339
3340 /*
3341 Reset the length of the UsefulInputBuf to what it was before
3342 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003343 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003344 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003345 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003346
3347
Laurence Lundblade02625d42020-06-25 14:41:41 -07003348 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003349 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003350}
3351
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003352
Laurence Lundbladee6430642020-03-14 21:15:44 -07003353
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003354
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003355
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003356
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003357
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003358
Laurence Lundblade93d89472020-10-03 22:30:50 -07003359static QCBORError
3360InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003361{
3362 switch(pItem->uDataType) {
3363 case QCBOR_TYPE_TRUE:
3364 *pBool = true;
3365 return QCBOR_SUCCESS;
3366 break;
3367
3368 case QCBOR_TYPE_FALSE:
3369 *pBool = false;
3370 return QCBOR_SUCCESS;
3371 break;
3372
3373 default:
3374 return QCBOR_ERR_UNEXPECTED_TYPE;
3375 break;
3376 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003377 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003378}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003379
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003380
Laurence Lundblade9b334962020-08-27 10:55:53 -07003381
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003382/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003383 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003384*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003385void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003386{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003387 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003388 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003389 return;
3390 }
3391
Laurence Lundbladec4537442020-04-14 18:53:22 -07003392 QCBORError nError;
3393 QCBORItem Item;
3394
3395 nError = QCBORDecode_GetNext(pMe, &Item);
3396 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003397 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003398 return;
3399 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003400 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003401}
3402
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003403
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003404/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003405 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003406*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003407void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003408{
3409 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003410 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003411
Laurence Lundblade9b334962020-08-27 10:55:53 -07003412 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003413}
3414
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003415
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003416/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003417 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003418*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003419void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3420{
3421 QCBORItem Item;
3422 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3423
Laurence Lundblade9b334962020-08-27 10:55:53 -07003424 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003425}
3426
3427
3428
Laurence Lundbladec7114722020-08-13 05:11:40 -07003429
3430static void ProcessEpochDate(QCBORDecodeContext *pMe,
3431 QCBORItem *pItem,
3432 uint8_t uTagRequirement,
3433 int64_t *pnTime)
3434{
3435 if(pMe->uLastError != QCBOR_SUCCESS) {
3436 // Already in error state, do nothing
3437 return;
3438 }
3439
3440 QCBORError uErr;
3441
3442 const TagSpecification TagSpec =
3443 {
3444 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003445 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3446 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003447 };
3448
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003449 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003450 if(uErr != QCBOR_SUCCESS) {
3451 goto Done;
3452 }
3453
3454 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3455 uErr = DecodeDateEpoch(pItem);
3456 if(uErr != QCBOR_SUCCESS) {
3457 goto Done;
3458 }
3459 }
3460
Laurence Lundblade9b334962020-08-27 10:55:53 -07003461 // Save the tags in the last item's tags in the decode context
3462 // for QCBORDecode_GetNthTagOfLast()
3463 CopyTags(pMe, pItem);
3464
Laurence Lundbladec7114722020-08-13 05:11:40 -07003465 *pnTime = pItem->val.epochDate.nSeconds;
3466
3467Done:
3468 pMe->uLastError = (uint8_t)uErr;
3469}
3470
3471
3472void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003473 uint8_t uTagRequirement,
3474 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003475{
3476 if(pMe->uLastError != QCBOR_SUCCESS) {
3477 // Already in error state, do nothing
3478 return;
3479 }
3480
3481 QCBORItem Item;
3482 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3483
3484 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3485}
3486
3487
3488void
3489QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3490 int64_t nLabel,
3491 uint8_t uTagRequirement,
3492 int64_t *pnTime)
3493{
3494 QCBORItem Item;
3495 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3496 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3497}
3498
3499
3500void
3501QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3502 const char *szLabel,
3503 uint8_t uTagRequirement,
3504 int64_t *pnTime)
3505{
3506 QCBORItem Item;
3507 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3508 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3509}
3510
3511
3512
3513
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003514void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3515 TagSpecification TagSpec,
3516 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003517{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003518 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003519 // Already in error state, do nothing
3520 return;
3521 }
3522
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003523 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003524 QCBORItem Item;
3525
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003526 uError = QCBORDecode_GetNext(pMe, &Item);
3527 if(uError != QCBOR_SUCCESS) {
3528 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003529 return;
3530 }
3531
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003532 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003533
3534 if(pMe->uLastError == QCBOR_SUCCESS) {
3535 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003536 } else {
3537 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003538 }
3539}
3540
Laurence Lundbladec4537442020-04-14 18:53:22 -07003541
3542
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003543
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003544static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003545 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003546 UsefulBufC *pValue,
3547 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003548{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003549 const TagSpecification TagSpec =
3550 {
3551 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003552 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3553 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003554 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003555
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003556 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003557 if(uErr != QCBOR_SUCCESS) {
3558 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003559 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003560
3561 *pValue = pItem->val.string;
3562
3563 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3564 *pbIsNegative = false;
3565 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3566 *pbIsNegative = true;
3567 }
3568
3569 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003570}
3571
3572
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003573/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003574 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003575 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003576void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3577 uint8_t uTagRequirement,
3578 UsefulBufC *pValue,
3579 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003580{
3581 if(pMe->uLastError != QCBOR_SUCCESS) {
3582 // Already in error state, do nothing
3583 return;
3584 }
3585
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003586 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003587 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3588 if(uError != QCBOR_SUCCESS) {
3589 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003590 return;
3591 }
3592
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003593 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003594}
3595
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003596
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003597/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003598 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003599*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003600void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3601 int64_t nLabel,
3602 uint8_t uTagRequirement,
3603 UsefulBufC *pValue,
3604 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003605{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003606 QCBORItem Item;
3607 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003608 if(pMe->uLastError != QCBOR_SUCCESS) {
3609 return;
3610 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003611
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003612 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003613}
3614
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003615
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003616/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003617 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003618*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003619void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3620 const char *szLabel,
3621 uint8_t uTagRequirement,
3622 UsefulBufC *pValue,
3623 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003624{
3625 QCBORItem Item;
3626 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003627 if(pMe->uLastError != QCBOR_SUCCESS) {
3628 return;
3629 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003630
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003631 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003632}
3633
3634
3635
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003636
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003637// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003638QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3639 const QCBORItem *pItem,
3640 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003641 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003642{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003643 const TagSpecification TagSpecText =
3644 {
3645 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003646 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3647 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003648 };
3649 const TagSpecification TagSpecBinary =
3650 {
3651 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003652 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3653 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003654 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003655
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003656 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003657
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003658 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003659 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003660 if(pbIsTag257 != NULL) {
3661 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003662 }
3663 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003664 } else if(CheckTagRequirement(TagSpecBinary, 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 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003668 }
3669 uReturn = QCBOR_SUCCESS;
3670
3671 } else {
3672 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3673 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003674
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003675 return uReturn;
3676}
3677
Laurence Lundblade93d89472020-10-03 22:30:50 -07003678// Improvement: add methods for wrapped CBOR, a simple alternate
3679// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003680
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003681
3682
3683
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003684#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003685
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003686typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003687
3688
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003689// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003690static QCBORError
3691Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003692{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003693 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003694
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003695 if(uResult != 0) {
3696 /* This loop will run a maximum of 19 times because
3697 * UINT64_MAX < 10 ^^ 19. More than that will cause
3698 * exit with the overflow error
3699 */
3700 for(; nExponent > 0; nExponent--) {
3701 if(uResult > UINT64_MAX / 10) {
3702 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3703 }
3704 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003705 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003706
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003707 for(; nExponent < 0; nExponent++) {
3708 uResult = uResult / 10;
3709 if(uResult == 0) {
3710 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3711 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003712 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003713 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003714 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003715
3716 *puResult = uResult;
3717
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003718 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003719}
3720
3721
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003722// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003723static QCBORError
3724Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003725{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003726 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003727
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003728 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003729
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003730 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003731 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003732 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003733 */
3734 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003735 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003736 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003737 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003738 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003739 nExponent--;
3740 }
3741
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003742 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003743 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003744 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3745 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003746 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003747 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003748 }
3749
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003750 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003751
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003752 return QCBOR_SUCCESS;
3753}
3754
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003755
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003756/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003757 Compute value with signed mantissa and signed result. Works with
3758 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003759 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003760static inline QCBORError ExponentiateNN(int64_t nMantissa,
3761 int64_t nExponent,
3762 int64_t *pnResult,
3763 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003764{
3765 uint64_t uResult;
3766
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003767 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003768 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003769 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3770
3771 // Do the exponentiation of the positive mantissa
3772 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3773 if(uReturn) {
3774 return uReturn;
3775 }
3776
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003777
Laurence Lundblade983500d2020-05-14 11:49:34 -07003778 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3779 of INT64_MIN. This assumes two's compliment representation where
3780 INT64_MIN is one increment farther from 0 than INT64_MAX.
3781 Trying to write -INT64_MIN doesn't work to get this because the
3782 compiler tries to work with an int64_t which can't represent
3783 -INT64_MIN.
3784 */
3785 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3786
3787 // Error out if too large
3788 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003789 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3790 }
3791
3792 // Casts are safe because of checks above
3793 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3794
3795 return QCBOR_SUCCESS;
3796}
3797
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003798
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003799/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003800 Compute value with signed mantissa and unsigned result. Works with
3801 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003802 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003803static inline QCBORError ExponentitateNU(int64_t nMantissa,
3804 int64_t nExponent,
3805 uint64_t *puResult,
3806 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003807{
3808 if(nMantissa < 0) {
3809 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3810 }
3811
3812 // Cast to unsigned is OK because of check for negative
3813 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3814 // Exponentiation is straight forward
3815 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3816}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003817
3818
3819/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003820 Compute value with signed mantissa and unsigned result. Works with
3821 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003822 */
3823static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3824 int64_t nExponent,
3825 uint64_t *puResult,
3826 fExponentiator pfExp)
3827{
3828 return (*pfExp)(uMantissa, nExponent, puResult);
3829}
3830
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003831#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3832
3833
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003834
3835
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003836
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003837static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003838{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003839 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003840
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003841 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003842 const uint8_t *pByte = BigNum.ptr;
3843 size_t uLen = BigNum.len;
3844 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003845 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003846 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003847 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003848 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003849 }
3850
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003851 *pResult = uResult;
3852 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003853}
3854
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003855
Laurence Lundblade887add82020-05-17 05:50:34 -07003856static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003857{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003858 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003859}
3860
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003861
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003862static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003863{
3864 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003865 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3866 if(uError) {
3867 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003868 }
3869 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3870 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003871 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003872}
3873
3874
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003875static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003876{
3877 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003878 /* The negative integer furthest from zero for a C int64_t is
3879 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3880 negative number in CBOR is computed as -n - 1 where n is the
3881 encoded integer, where n is what is in the variable BigNum. When
3882 converting BigNum to a uint64_t, the maximum value is thus
3883 INT64_MAX, so that when it -n - 1 is applied to it the result will
3884 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003885
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003886 -n - 1 <= INT64_MIN.
3887 -n - 1 <= -INT64_MAX - 1
3888 n <= INT64_MAX.
3889 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003890 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003891 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003892 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003893 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003894
3895 /// Now apply -n - 1. The cast is safe because
3896 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3897 // is the largest positive integer that an int64_t can
3898 // represent. */
3899 *pnResult = -(int64_t)uResult - 1;
3900
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003901 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003902}
3903
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003904
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003905
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003906
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003907
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003908/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003909Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003910
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003911\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003912
Laurence Lundblade93d89472020-10-03 22:30:50 -07003913\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
3914 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003915
3916\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3917
Laurence Lundblade93d89472020-10-03 22:30:50 -07003918\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
3919 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003920*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07003921static QCBORError
3922ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003923{
3924 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003925 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003926 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003927#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003928 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003929 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3930 http://www.cplusplus.com/reference/cmath/llround/
3931 */
3932 // Not interested in FE_INEXACT
3933 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003934 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3935 *pnValue = llround(pItem->val.dfnum);
3936 } else {
3937 *pnValue = lroundf(pItem->val.fnum);
3938 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003939 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
3940 // llround() shouldn't result in divide by zero, but catch
3941 // it here in case it unexpectedly does. Don't try to
3942 // distinguish between the various exceptions because it seems
3943 // they vary by CPU, compiler and OS.
3944 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003945 }
3946 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003947 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003948 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003949#else
3950 return QCBOR_ERR_HW_FLOAT_DISABLED;
3951#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003952 break;
3953
3954 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003955 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003956 *pnValue = pItem->val.int64;
3957 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003958 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003959 }
3960 break;
3961
3962 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003963 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003964 if(pItem->val.uint64 < INT64_MAX) {
3965 *pnValue = pItem->val.int64;
3966 } else {
3967 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3968 }
3969 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003970 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003971 }
3972 break;
3973
3974 default:
3975 return QCBOR_ERR_UNEXPECTED_TYPE;
3976 }
3977 return QCBOR_SUCCESS;
3978}
3979
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003980
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003981void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003982 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003983 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003984 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003985{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003986 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003987 return;
3988 }
3989
Laurence Lundbladee6430642020-03-14 21:15:44 -07003990 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003991 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3992 if(uError) {
3993 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003994 return;
3995 }
3996
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003997 if(pItem) {
3998 *pItem = Item;
3999 }
4000
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004001 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004002}
4003
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004004
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004005void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4006 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004007 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004008 int64_t *pnValue,
4009 QCBORItem *pItem)
4010{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004011 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004012 if(pMe->uLastError != QCBOR_SUCCESS) {
4013 return;
4014 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004015
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004016 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004017}
4018
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004019
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004020void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4021 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004022 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004023 int64_t *pnValue,
4024 QCBORItem *pItem)
4025{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004026 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004027 if(pMe->uLastError != QCBOR_SUCCESS) {
4028 return;
4029 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004030
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004031 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004032}
4033
4034
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004035/*
4036 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004037
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004038 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004039
Laurence Lundblade93d89472020-10-03 22:30:50 -07004040 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4041 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004042
4043 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4044
Laurence Lundblade93d89472020-10-03 22:30:50 -07004045 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4046 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004047 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004048static QCBORError
4049Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004050{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004051 switch(pItem->uDataType) {
4052
4053 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004054 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004055 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004056 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004057 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004058 }
4059 break;
4060
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004061 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004062 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004063 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004064 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004065 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004066 }
4067 break;
4068
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004069#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4070 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004071 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004072 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004073 pItem->val.expAndMantissa.nExponent,
4074 pnValue,
4075 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004076 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004077 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004078 }
4079 break;
4080
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004081 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004082 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004083 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004084 pItem->val.expAndMantissa.nExponent,
4085 pnValue,
4086 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004087 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004088 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004089 }
4090 break;
4091
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004092 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004093 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004094 int64_t nMantissa;
4095 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004096 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4097 if(uErr) {
4098 return uErr;
4099 }
4100 return ExponentiateNN(nMantissa,
4101 pItem->val.expAndMantissa.nExponent,
4102 pnValue,
4103 Exponentitate10);
4104 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004105 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004106 }
4107 break;
4108
4109 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004110 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004111 int64_t nMantissa;
4112 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004113 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4114 if(uErr) {
4115 return uErr;
4116 }
4117 return ExponentiateNN(nMantissa,
4118 pItem->val.expAndMantissa.nExponent,
4119 pnValue,
4120 Exponentitate10);
4121 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004122 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004123 }
4124 break;
4125
4126 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004127 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004128 int64_t nMantissa;
4129 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004130 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4131 if(uErr) {
4132 return uErr;
4133 }
4134 return ExponentiateNN(nMantissa,
4135 pItem->val.expAndMantissa.nExponent,
4136 pnValue,
4137 Exponentitate2);
4138 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004139 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004140 }
4141 break;
4142
4143 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004144 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004145 int64_t nMantissa;
4146 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004147 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4148 if(uErr) {
4149 return uErr;
4150 }
4151 return ExponentiateNN(nMantissa,
4152 pItem->val.expAndMantissa.nExponent,
4153 pnValue,
4154 Exponentitate2);
4155 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004156 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004157 }
4158 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004159#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4160
Laurence Lundbladee6430642020-03-14 21:15:44 -07004161
Laurence Lundbladec4537442020-04-14 18:53:22 -07004162 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004163 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004164}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004165
4166
Laurence Lundbladec4537442020-04-14 18:53:22 -07004167/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004168 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004169 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004170void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004171{
4172 QCBORItem Item;
4173
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004174 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004175
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004176 if(pMe->uLastError == QCBOR_SUCCESS) {
4177 // The above conversion succeeded
4178 return;
4179 }
4180
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004181 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004182 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004183 return;
4184 }
4185
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004186 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004187}
4188
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004189
4190/*
4191Public function, see header qcbor/qcbor_decode.h file
4192*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004193void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4194 int64_t nLabel,
4195 uint32_t uConvertTypes,
4196 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004197{
4198 QCBORItem Item;
4199
Laurence Lundblade93d89472020-10-03 22:30:50 -07004200 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4201 nLabel,
4202 uConvertTypes,
4203 pnValue,
4204 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004205
4206 if(pMe->uLastError == QCBOR_SUCCESS) {
4207 // The above conversion succeeded
4208 return;
4209 }
4210
4211 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4212 // The above conversion failed in a way that code below can't correct
4213 return;
4214 }
4215
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004216 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004217}
4218
4219
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004220/*
4221Public function, see header qcbor/qcbor_decode.h file
4222*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004223void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4224 const char *szLabel,
4225 uint32_t uConvertTypes,
4226 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004227{
4228 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004229 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4230 szLabel,
4231 uConvertTypes,
4232 pnValue,
4233 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004234
4235 if(pMe->uLastError == QCBOR_SUCCESS) {
4236 // The above conversion succeeded
4237 return;
4238 }
4239
4240 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4241 // The above conversion failed in a way that code below can't correct
4242 return;
4243 }
4244
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004245 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004246}
4247
4248
Laurence Lundblade93d89472020-10-03 22:30:50 -07004249static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004250{
4251 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004252 case QCBOR_TYPE_DOUBLE:
4253 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004254#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004255 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004256 // Can't use llround here because it will not convert values
4257 // greater than INT64_MAX and less than UINT64_MAX that
4258 // need to be converted so it is more complicated.
4259 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4260 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4261 if(isnan(pItem->val.dfnum)) {
4262 return QCBOR_ERR_FLOAT_EXCEPTION;
4263 } else if(pItem->val.dfnum < 0) {
4264 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4265 } else {
4266 double dRounded = round(pItem->val.dfnum);
4267 // See discussion in DecodeDateEpoch() for
4268 // explanation of - 0x7ff
4269 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4270 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4271 }
4272 *puValue = (uint64_t)dRounded;
4273 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004274 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004275 if(isnan(pItem->val.fnum)) {
4276 return QCBOR_ERR_FLOAT_EXCEPTION;
4277 } else if(pItem->val.fnum < 0) {
4278 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4279 } else {
4280 float fRounded = roundf(pItem->val.fnum);
4281 // See discussion in DecodeDateEpoch() for
4282 // explanation of - 0x7ff
4283 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4284 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4285 }
4286 *puValue = (uint64_t)fRounded;
4287 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004288 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004289 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4290 // round() and roundf() shouldn't result in exceptions here, but
4291 // catch them to be robust and thorough. Don't try to
4292 // distinguish between the various exceptions because it seems
4293 // they vary by CPU, compiler and OS.
4294 return QCBOR_ERR_FLOAT_EXCEPTION;
4295 }
4296
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004297 } else {
4298 return QCBOR_ERR_UNEXPECTED_TYPE;
4299 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004300#else
4301 return QCBOR_ERR_HW_FLOAT_DISABLED;
4302#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004303 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004304
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004305 case QCBOR_TYPE_INT64:
4306 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4307 if(pItem->val.int64 >= 0) {
4308 *puValue = (uint64_t)pItem->val.int64;
4309 } else {
4310 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4311 }
4312 } else {
4313 return QCBOR_ERR_UNEXPECTED_TYPE;
4314 }
4315 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004316
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004317 case QCBOR_TYPE_UINT64:
4318 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4319 *puValue = pItem->val.uint64;
4320 } else {
4321 return QCBOR_ERR_UNEXPECTED_TYPE;
4322 }
4323 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004324
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004325 default:
4326 return QCBOR_ERR_UNEXPECTED_TYPE;
4327 }
4328
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004329 return QCBOR_SUCCESS;
4330}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004331
4332
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004333void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004334 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004335 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004336 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004337{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004338 if(pMe->uLastError != QCBOR_SUCCESS) {
4339 return;
4340 }
4341
Laurence Lundbladec4537442020-04-14 18:53:22 -07004342 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004343
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004344 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4345 if(uError) {
4346 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004347 return;
4348 }
4349
Laurence Lundbladea826c502020-05-10 21:07:00 -07004350 if(pItem) {
4351 *pItem = Item;
4352 }
4353
Laurence Lundblade93d89472020-10-03 22:30:50 -07004354 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004355}
4356
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004357
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004358void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004359 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004360 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004361 uint64_t *puValue,
4362 QCBORItem *pItem)
4363{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004364 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004365 if(pMe->uLastError != QCBOR_SUCCESS) {
4366 return;
4367 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004368
Laurence Lundblade93d89472020-10-03 22:30:50 -07004369 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004370}
4371
4372
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004373void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004374 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004375 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004376 uint64_t *puValue,
4377 QCBORItem *pItem)
4378{
4379 if(pMe->uLastError != QCBOR_SUCCESS) {
4380 return;
4381 }
4382
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004383 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004384 if(pMe->uLastError != QCBOR_SUCCESS) {
4385 return;
4386 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004387
Laurence Lundblade93d89472020-10-03 22:30:50 -07004388 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004389}
4390
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004391
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004392
Laurence Lundblade93d89472020-10-03 22:30:50 -07004393static QCBORError
4394UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004395{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004396 switch(pItem->uDataType) {
4397
4398 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004399 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004400 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4401 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004402 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004403 }
4404 break;
4405
4406 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004407 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004408 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4409 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004410 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004411 }
4412 break;
4413
4414#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4415
4416 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004417 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004418 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004419 pItem->val.expAndMantissa.nExponent,
4420 puValue,
4421 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004422 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004423 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004424 }
4425 break;
4426
4427 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004428 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004429 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4430 pItem->val.expAndMantissa.nExponent,
4431 puValue,
4432 Exponentitate2);
4433 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004434 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004435 }
4436 break;
4437
4438 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004439 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004440 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004441 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004442 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004443 if(uErr != QCBOR_SUCCESS) {
4444 return uErr;
4445 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004446 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004447 pItem->val.expAndMantissa.nExponent,
4448 puValue,
4449 Exponentitate10);
4450 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004451 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004452 }
4453 break;
4454
4455 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004456 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004457 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4458 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004459 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004460 }
4461 break;
4462
4463 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004464 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004465 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004466 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004467 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004468 if(uErr != QCBOR_SUCCESS) {
4469 return uErr;
4470 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004471 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004472 pItem->val.expAndMantissa.nExponent,
4473 puValue,
4474 Exponentitate2);
4475 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004476 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004477 }
4478 break;
4479
4480 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004481 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004482 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4483 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004484 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004485 }
4486 break;
4487#endif
4488 default:
4489 return QCBOR_ERR_UNEXPECTED_TYPE;
4490 }
4491}
4492
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004493
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004494/*
4495 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004496 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004497void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004498{
4499 QCBORItem Item;
4500
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004501 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004502
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004503 if(pMe->uLastError == QCBOR_SUCCESS) {
4504 // The above conversion succeeded
4505 return;
4506 }
4507
4508 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4509 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004510 return;
4511 }
4512
Laurence Lundblade93d89472020-10-03 22:30:50 -07004513 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004514}
4515
Laurence Lundbladec4537442020-04-14 18:53:22 -07004516
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004517/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004518 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004519*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004520void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004521 int64_t nLabel,
4522 uint32_t uConvertTypes,
4523 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004524{
4525 QCBORItem Item;
4526
Laurence Lundblade93d89472020-10-03 22:30:50 -07004527 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4528 nLabel,
4529 uConvertTypes,
4530 puValue,
4531 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004532
4533 if(pMe->uLastError == QCBOR_SUCCESS) {
4534 // The above conversion succeeded
4535 return;
4536 }
4537
4538 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4539 // The above conversion failed in a way that code below can't correct
4540 return;
4541 }
4542
Laurence Lundblade93d89472020-10-03 22:30:50 -07004543 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004544}
4545
4546
4547/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004548 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004549*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004550void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004551 const char *szLabel,
4552 uint32_t uConvertTypes,
4553 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004554{
4555 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004556 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4557 szLabel,
4558 uConvertTypes,
4559 puValue,
4560 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004561
4562 if(pMe->uLastError == QCBOR_SUCCESS) {
4563 // The above conversion succeeded
4564 return;
4565 }
4566
4567 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4568 // The above conversion failed in a way that code below can't correct
4569 return;
4570 }
4571
Laurence Lundblade93d89472020-10-03 22:30:50 -07004572 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004573}
4574
4575
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004576
4577
Laurence Lundblade9b334962020-08-27 10:55:53 -07004578static QCBORError ConvertDouble(const QCBORItem *pItem,
4579 uint32_t uConvertTypes,
4580 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004581{
4582 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004583 case QCBOR_TYPE_FLOAT:
4584#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4585 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4586 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004587 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004588 *pdValue = (double)pItem->val.fnum;
4589 } else {
4590 return QCBOR_ERR_UNEXPECTED_TYPE;
4591 }
4592 }
4593#else
4594 return QCBOR_ERR_HW_FLOAT_DISABLED;
4595#endif
4596 break;
4597
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004598 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004599 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4600 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004601 *pdValue = pItem->val.dfnum;
4602 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004603 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004604 }
4605 }
4606 break;
4607
4608 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004609#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004610 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004611 // A simple cast seems to do the job with no worry of exceptions.
4612 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004613 *pdValue = (double)pItem->val.int64;
4614
4615 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004616 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004617 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004618#else
4619 return QCBOR_ERR_HW_FLOAT_DISABLED;
4620#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004621 break;
4622
4623 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004624#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004625 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004626 // A simple cast seems to do the job with no worry of exceptions.
4627 // There will be precision loss for some values.
4628 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004629 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004630 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004631 }
4632 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004633#else
4634 return QCBOR_ERR_HW_FLOAT_DISABLED;
4635#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004636
4637 default:
4638 return QCBOR_ERR_UNEXPECTED_TYPE;
4639 }
4640
4641 return QCBOR_SUCCESS;
4642}
4643
4644
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004645void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004646 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004647 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004648 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004649{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004650 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004651 return;
4652 }
4653
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004654 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004655
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004656 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004657 if(uError) {
4658 pMe->uLastError = (uint8_t)uError;
4659 return;
4660 }
4661
4662 if(pItem) {
4663 *pItem = Item;
4664 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004665
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004666 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004667}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004668
Laurence Lundbladec4537442020-04-14 18:53:22 -07004669
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004670void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4671 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004672 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004673 double *pdValue,
4674 QCBORItem *pItem)
4675{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004676 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004677 if(pMe->uLastError != QCBOR_SUCCESS) {
4678 return;
4679 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004680
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004681 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004682}
4683
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004684
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004685void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4686 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004687 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004688 double *pdValue,
4689 QCBORItem *pItem)
4690{
4691 if(pMe->uLastError != QCBOR_SUCCESS) {
4692 return;
4693 }
4694
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004695 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004696 if(pMe->uLastError != QCBOR_SUCCESS) {
4697 return;
4698 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004699
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004700 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004701}
4702
4703
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004704#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004705static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4706{
4707 double dResult;
4708
4709 dResult = 0.0;
4710 const uint8_t *pByte = BigNum.ptr;
4711 size_t uLen = BigNum.len;
4712 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004713 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004714 while(uLen--) {
4715 dResult = (dResult * 256.0) + (double)*pByte++;
4716 }
4717
4718 return dResult;
4719}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004720#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4721
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004722
Laurence Lundblade93d89472020-10-03 22:30:50 -07004723static QCBORError
4724DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004725{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004726#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004727 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004728 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4729
4730 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004731 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004732
4733#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004734 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004735 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004736 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004737 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4738 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4739 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004740 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004741 }
4742 break;
4743
4744 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004745 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004746 // Underflow gives 0, overflow gives infinity
4747 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4748 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004749 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004750 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004751 }
4752 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004753#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004754
4755 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004756 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004757 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4758 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004759 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004760 }
4761 break;
4762
4763 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004764 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004765 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004766 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004767 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004768 }
4769 break;
4770
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004771#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004772 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004773 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004774 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4775 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4776 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004777 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004778 }
4779 break;
4780
4781 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004782 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004783 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4784 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4785 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004786 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004787 }
4788 break;
4789
4790 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004791 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004792 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4793 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4794 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004795 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004796 }
4797 break;
4798
4799 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004800 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004801 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004802 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4803 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004804 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004805 }
4806 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004807#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4808
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004809 default:
4810 return QCBOR_ERR_UNEXPECTED_TYPE;
4811 }
4812
4813 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004814
4815#else
4816 (void)pItem;
4817 (void)uConvertTypes;
4818 (void)pdValue;
4819 return QCBOR_ERR_HW_FLOAT_DISABLED;
4820#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4821
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004822}
4823
4824
4825/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004826 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004827*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004828void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4829 uint32_t uConvertTypes,
4830 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004831{
4832
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004833 QCBORItem Item;
4834
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004835 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004836
4837 if(pMe->uLastError == QCBOR_SUCCESS) {
4838 // The above conversion succeeded
4839 return;
4840 }
4841
4842 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4843 // The above conversion failed in a way that code below can't correct
4844 return;
4845 }
4846
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004847 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004848}
4849
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004850
4851/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004852 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004853*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004854void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4855 int64_t nLabel,
4856 uint32_t uConvertTypes,
4857 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004858{
4859 QCBORItem Item;
4860
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004861 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004862
4863 if(pMe->uLastError == QCBOR_SUCCESS) {
4864 // The above conversion succeeded
4865 return;
4866 }
4867
4868 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4869 // The above conversion failed in a way that code below can't correct
4870 return;
4871 }
4872
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004873 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004874}
4875
4876
4877/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004878 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004879*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004880void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4881 const char *szLabel,
4882 uint32_t uConvertTypes,
4883 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004884{
4885 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004886 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004887
4888 if(pMe->uLastError == QCBOR_SUCCESS) {
4889 // The above conversion succeeded
4890 return;
4891 }
4892
4893 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4894 // The above conversion failed in a way that code below can't correct
4895 return;
4896 }
4897
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004898 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004899}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004900
4901
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004902
4903
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004904#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004905static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4906{
4907 while((uInt & 0xff00000000000000UL) == 0) {
4908 uInt = uInt << 8;
4909 };
4910
4911 UsefulOutBuf UOB;
4912
4913 UsefulOutBuf_Init(&UOB, Buffer);
4914
4915 while(uInt) {
4916 const uint64_t xx = uInt & 0xff00000000000000UL;
4917 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4918 uInt = uInt << 8;
4919 (void)xx;
4920 }
4921
4922 return UsefulOutBuf_OutUBuf(&UOB);
4923}
4924
4925
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004926static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4927 TagSpecification TagSpec,
4928 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004929{
4930 QCBORError uErr;
4931 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004932 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004933 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004934 if(uErr != QCBOR_SUCCESS) {
4935 goto Done;
4936 }
4937
4938 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4939 break; // Successful exit. Moving on to finish decoding.
4940 }
4941
4942 // The item is an array, which means an undecoded
4943 // mantissa and exponent, so decode it. It will then
4944 // have a different type and exit the loop if.
4945 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4946 if(uErr != QCBOR_SUCCESS) {
4947 goto Done;
4948 }
4949
4950 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07004951 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004952 }
4953Done:
4954 return uErr;
4955}
4956
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004957
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004958static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004959 TagSpecification TagSpec,
4960 QCBORItem *pItem,
4961 int64_t *pnMantissa,
4962 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004963{
4964 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004965
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004966 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004967 if(uErr != QCBOR_SUCCESS) {
4968 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004969 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004970
Laurence Lundblade9b334962020-08-27 10:55:53 -07004971 switch (pItem->uDataType) {
4972
4973 case QCBOR_TYPE_DECIMAL_FRACTION:
4974 case QCBOR_TYPE_BIGFLOAT:
4975 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4976 *pnExponent = pItem->val.expAndMantissa.nExponent;
4977 break;
4978
4979 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4980 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4981 *pnExponent = pItem->val.expAndMantissa.nExponent;
4982 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4983 break;
4984
4985 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4986 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4987 *pnExponent = pItem->val.expAndMantissa.nExponent;
4988 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4989 break;
4990
4991 default:
4992 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
4993 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004994
4995 Done:
4996 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004997}
4998
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004999
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005000static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005001 TagSpecification TagSpec,
5002 QCBORItem *pItem,
5003 UsefulBuf BufferForMantissa,
5004 UsefulBufC *pMantissa,
5005 bool *pbIsNegative,
5006 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005007{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005008 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005009
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005010 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005011 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005012 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005013 }
5014
5015 uint64_t uMantissa;
5016
5017 switch (pItem->uDataType) {
5018
5019 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005020 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005021 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5022 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5023 *pbIsNegative = false;
5024 } else {
5025 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5026 *pbIsNegative = true;
5027 }
5028 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5029 *pnExponent = pItem->val.expAndMantissa.nExponent;
5030 break;
5031
5032 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005033 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005034 *pnExponent = pItem->val.expAndMantissa.nExponent;
5035 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5036 *pbIsNegative = false;
5037 break;
5038
5039 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005040 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005041 *pnExponent = pItem->val.expAndMantissa.nExponent;
5042 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5043 *pbIsNegative = true;
5044 break;
5045
5046 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005047 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005048 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005049
5050Done:
5051 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005052}
5053
5054
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005055/*
5056 Public function, see header qcbor/qcbor_decode.h file
5057*/
5058void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5059 uint8_t uTagRequirement,
5060 int64_t *pnMantissa,
5061 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005062{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005063 if(pMe->uLastError != QCBOR_SUCCESS) {
5064 return;
5065 }
5066
5067 QCBORItem Item;
5068 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5069 if(uError) {
5070 pMe->uLastError = (uint8_t)uError;
5071 return;
5072 }
5073
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005074 const TagSpecification TagSpec =
5075 {
5076 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005077 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5078 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5079 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005080 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005081
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005082 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005083}
5084
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005085
5086/*
5087 Public function, see header qcbor/qcbor_decode.h file
5088*/
5089void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005090 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005091 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005092 int64_t *pnMantissa,
5093 int64_t *pnExponent)
5094{
5095 if(pMe->uLastError != QCBOR_SUCCESS) {
5096 return;
5097 }
5098
5099 QCBORItem Item;
5100 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5101
5102 const TagSpecification TagSpec =
5103 {
5104 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005105 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5106 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5107 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005108 };
5109
5110 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5111}
5112
5113
5114/*
5115 Public function, see header qcbor/qcbor_decode.h file
5116*/
5117void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005118 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005119 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005120 int64_t *pnMantissa,
5121 int64_t *pnExponent)
5122{
5123 if(pMe->uLastError != QCBOR_SUCCESS) {
5124 return;
5125 }
5126
5127 QCBORItem Item;
5128 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5129
5130 const TagSpecification TagSpec =
5131 {
5132 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005133 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5134 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5135 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005136 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005137
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005138 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5139}
5140
5141
5142/*
5143 Public function, see header qcbor/qcbor_decode.h file
5144*/
5145void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5146 uint8_t uTagRequirement,
5147 UsefulBuf MantissaBuffer,
5148 UsefulBufC *pMantissa,
5149 bool *pbMantissaIsNegative,
5150 int64_t *pnExponent)
5151{
5152 if(pMe->uLastError != QCBOR_SUCCESS) {
5153 return;
5154 }
5155
5156 QCBORItem Item;
5157 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5158 if(uError) {
5159 pMe->uLastError = (uint8_t)uError;
5160 return;
5161 }
5162
5163 const TagSpecification TagSpec =
5164 {
5165 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005166 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5167 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5168 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005169 };
5170
Laurence Lundblade93d89472020-10-03 22:30:50 -07005171 ProcessMantissaAndExponentBig(pMe,
5172 TagSpec,
5173 &Item,
5174 MantissaBuffer,
5175 pMantissa,
5176 pbMantissaIsNegative,
5177 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005178}
5179
5180
5181/*
5182 Public function, see header qcbor/qcbor_decode.h file
5183*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005184void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005185 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005186 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005187 UsefulBuf BufferForMantissa,
5188 UsefulBufC *pMantissa,
5189 bool *pbIsNegative,
5190 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005191{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005192 if(pMe->uLastError != QCBOR_SUCCESS) {
5193 return;
5194 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005195
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005196 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005197 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005198 if(pMe->uLastError != QCBOR_SUCCESS) {
5199 return;
5200 }
5201
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005202 const TagSpecification TagSpec =
5203 {
5204 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005205 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5206 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5207 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005208 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005209
Laurence Lundblade93d89472020-10-03 22:30:50 -07005210 ProcessMantissaAndExponentBig(pMe,
5211 TagSpec,
5212 &Item,
5213 BufferForMantissa,
5214 pMantissa,
5215 pbIsNegative,
5216 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005217}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005218
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005219
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005220/*
5221 Public function, see header qcbor/qcbor_decode.h file
5222*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005223void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005224 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005225 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005226 UsefulBuf BufferForMantissa,
5227 UsefulBufC *pMantissa,
5228 bool *pbIsNegative,
5229 int64_t *pnExponent)
5230{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005231 if(pMe->uLastError != QCBOR_SUCCESS) {
5232 return;
5233 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005234
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005235 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005236 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5237 if(pMe->uLastError != QCBOR_SUCCESS) {
5238 return;
5239 }
5240
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005241 const TagSpecification TagSpec =
5242 {
5243 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005244 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5245 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5246 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005247 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005248
5249 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5250}
5251
5252
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005253/*
5254 Public function, see header qcbor/qcbor_decode.h file
5255*/
5256void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5257 uint8_t uTagRequirement,
5258 int64_t *pnMantissa,
5259 int64_t *pnExponent)
5260{
5261 if(pMe->uLastError != QCBOR_SUCCESS) {
5262 return;
5263 }
5264
5265 QCBORItem Item;
5266 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5267 if(uError) {
5268 pMe->uLastError = (uint8_t)uError;
5269 return;
5270 }
5271 const TagSpecification TagSpec =
5272 {
5273 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005274 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5275 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5276 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005277 };
5278
5279 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5280}
5281
5282
5283/*
5284 Public function, see header qcbor/qcbor_decode.h file
5285*/
5286void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005287 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005288 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005289 int64_t *pnMantissa,
5290 int64_t *pnExponent)
5291{
5292 if(pMe->uLastError != QCBOR_SUCCESS) {
5293 return;
5294 }
5295
5296 QCBORItem Item;
5297 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5298 if(pMe->uLastError != QCBOR_SUCCESS) {
5299 return;
5300 }
5301
5302 const TagSpecification TagSpec =
5303 {
5304 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005305 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5306 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5307 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005308 };
5309
5310 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5311}
5312
5313
5314/*
5315 Public function, see header qcbor/qcbor_decode.h file
5316*/
5317void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005318 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005319 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005320 int64_t *pnMantissa,
5321 int64_t *pnExponent)
5322{
5323 if(pMe->uLastError != QCBOR_SUCCESS) {
5324 return;
5325 }
5326
5327 QCBORItem Item;
5328 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5329 if(pMe->uLastError != QCBOR_SUCCESS) {
5330 return;
5331 }
5332
5333 const TagSpecification TagSpec =
5334 {
5335 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005336 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5337 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5338 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005339 };
5340
5341 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5342}
5343
5344
5345/*
5346 Public function, see header qcbor/qcbor_decode.h file
5347*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005348void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5349 uint8_t uTagRequirement,
5350 UsefulBuf MantissaBuffer,
5351 UsefulBufC *pMantissa,
5352 bool *pbMantissaIsNegative,
5353 int64_t *pnExponent)
5354{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005355 if(pMe->uLastError != QCBOR_SUCCESS) {
5356 return;
5357 }
5358
5359 QCBORItem Item;
5360 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5361 if(uError) {
5362 pMe->uLastError = (uint8_t)uError;
5363 return;
5364 }
5365
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005366 const TagSpecification TagSpec =
5367 {
5368 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005369 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5370 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5371 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005372 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005373
5374 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005375}
5376
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005377
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005378/*
5379 Public function, see header qcbor/qcbor_decode.h file
5380*/
5381void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005382 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005383 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005384 UsefulBuf BufferForMantissa,
5385 UsefulBufC *pMantissa,
5386 bool *pbIsNegative,
5387 int64_t *pnExponent)
5388{
5389 if(pMe->uLastError != QCBOR_SUCCESS) {
5390 return;
5391 }
5392
5393 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005394 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5395 if(pMe->uLastError != QCBOR_SUCCESS) {
5396 return;
5397 }
5398
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005399 const TagSpecification TagSpec =
5400 {
5401 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005402 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5403 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5404 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005405 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005406
Laurence Lundblade93d89472020-10-03 22:30:50 -07005407 ProcessMantissaAndExponentBig(pMe,
5408 TagSpec,
5409 &Item,
5410 BufferForMantissa,
5411 pMantissa,
5412 pbIsNegative,
5413 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005414}
5415
5416
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005417/*
5418 Public function, see header qcbor/qcbor_decode.h file
5419*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005420void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005421 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005422 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005423 UsefulBuf BufferForMantissa,
5424 UsefulBufC *pMantissa,
5425 bool *pbIsNegative,
5426 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005427{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005428 if(pMe->uLastError != QCBOR_SUCCESS) {
5429 return;
5430 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005431
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005432 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005433 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5434 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005435 return;
5436 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005437
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005438 const TagSpecification TagSpec =
5439 {
5440 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005441 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5442 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5443 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005444 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005445
Laurence Lundblade93d89472020-10-03 22:30:50 -07005446 ProcessMantissaAndExponentBig(pMe,
5447 TagSpec,
5448 &Item,
5449 BufferForMantissa,
5450 pMantissa,
5451 pbIsNegative,
5452 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005453}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005454
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005455#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */