blob: aee158165f02ddbf4939d2f2f2678c2dd7a413c7 [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 Lundblade02625d42020-06-25 14:41:41 -070054inline static 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
63inline static bool
64QCBORItem_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
76inline static bool
77QCBORItem_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 Lundblade93d89472020-10-03 22:30:50 -070095 See commecnts about and typedef of QCBORDecodeNesting in qcbor_private.h,
96 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
100inline static 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 Lundblade1d85d522020-06-22 13:24:59 -0700112inline static 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 Lundblade9c905e82020-04-25 11:31:38 -0700142inline static 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 Lundblade3f9ef042020-04-14 13:15:51 -0700153inline static 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 Lundblade642282a2020-06-23 12:00:33 -0700169inline static 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 Lundblade6c8a4442020-06-22 22:16:11 -0700180inline static 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 Lundblade085d7952020-07-24 10:26:30 -0700192inline static 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 Lundbladea8edadb2020-06-27 22:35:37 -0700208inline static 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 Lundblade1d85d522020-06-22 13:24:59 -0700214inline static 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 Lundblade1d85d522020-06-22 13:24:59 -0700239inline static 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 Lundblade1d85d522020-06-22 13:24:59 -0700251inline static bool
252DecodeNesting_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 Lundblade2b843b52020-06-16 20:51:03 -0700262inline static 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 Lundbladed8c82c52020-06-12 22:15:52 -0700277inline static 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 Lundblade0a042a92020-06-12 14:09:50 -0700285inline static 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
293inline static 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 Lundbladeabf5c572020-06-29 21:21:29 -0700317inline static 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 Lundblade24d509a2020-06-06 18:43:15 -0700341inline static 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 Lundblade1d85d522020-06-22 13:24:59 -0700403inline static 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 Lundbladeee851742020-01-08 08:37:05 -0800434inline static 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 Lundblade410c7e02020-06-25 23:35:29 -0700443inline static 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 Lundblade4c0cf842019-01-12 03:25:44 -0800592inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
593 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 Lundbladeee851742020-01-08 08:37:05 -0800666inline static QCBORError
667DecodeInteger(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 Lundbladeee851742020-01-08 08:37:05 -0800736inline static 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 Lundblade1d7eb632019-02-17 17:23:38 -0800837inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
838 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 Lundblade9b334962020-08-27 10:55:53 -07001147 const int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001148 return me->auMappedTags[x];
1149 }
1150}
1151
Laurence Lundblade9b334962020-08-27 10:55:53 -07001152
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001153/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001154 Gets all optional tag data items preceding a data item that is not an
1155 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001156
1157 @retval QCBOR_ERR_UNSUPPORTED
1158
1159 @retval QCBOR_ERR_HIT_END
1160
1161 @retval QCBOR_ERR_INT_OVERFLOW
1162
1163 @retval QCBOR_ERR_STRING_ALLOCATE
1164
1165 @retval QCBOR_ERR_STRING_TOO_LONG
1166
1167 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1168
1169 @retval QCBOR_ERR_BAD_TYPE_7
1170
1171 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1172
1173 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1174
1175 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001176 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001177static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001178GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001179{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001180 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1181 CBOR_TAG_INVALID16,
1182 CBOR_TAG_INVALID16,
1183 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001184
Laurence Lundblade9b334962020-08-27 10:55:53 -07001185 QCBORError uReturn = QCBOR_SUCCESS;
1186
Laurence Lundblade59289e52019-12-30 13:44:37 -08001187 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001188 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001189 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1190 if(uErr != QCBOR_SUCCESS) {
1191 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001192 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001193 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001194
Laurence Lundblade9b334962020-08-27 10:55:53 -07001195 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001196 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001197 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001198 break;
1199 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001200
Laurence Lundblade9b334962020-08-27 10:55:53 -07001201 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1202 // No room in the tag list
1203 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1204 // Continue on to get all tags on this item even though
1205 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001206 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001207 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001208 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001209 // Slide tags over one in the array to make room at index 0
1210 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1211 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001212 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001213
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001214 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001215 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001216 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001217 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001218 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001219 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001220 break;
1221 }
1222 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1223 break;
1224 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001225 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001226 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1227 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001228 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1229 // Continue on to get all tags on this item even though
1230 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001231 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001232 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001233 }
1234
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001235 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001236 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001237 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001238
1239 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001240 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001241 }
1242 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001243
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001244Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001245 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001246}
1247
1248
1249/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001250 This layer takes care of map entries. It combines the label and data
1251 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001252
1253 @retval QCBOR_ERR_UNSUPPORTED
1254
1255 @retval QCBOR_ERR_HIT_END
1256
1257 @retval QCBOR_ERR_INT_OVERFLOW
1258
1259 @retval QCBOR_ERR_STRING_ALLOCATE
1260
1261 @retval QCBOR_ERR_STRING_TOO_LONG
1262
1263 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1264
1265 @retval QCBOR_ERR_BAD_TYPE_7
1266
1267 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1268
1269 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1270
1271 @retval QCBOR_ERR_TOO_MANY_TAGS
1272
1273 @retval QCBOR_ERR_MAP_LABEL_TYPE
1274
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001275 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001276 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001277static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001278GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001279{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001280 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001281 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001282 if(nReturn)
1283 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001284
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001285 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001286 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001287 goto Done;
1288 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001289
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001290 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1291 // In a map and caller wants maps decoded, not treated as arrays
1292
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001293 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001294 // If in a map and the right decoding mode, get the label
1295
Laurence Lundbladeee851742020-01-08 08:37:05 -08001296 // Save label in pDecodedItem and get the next which will
1297 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001298 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001299 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001300 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001301 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001302 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001303
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301304 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001305
1306 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1307 // strings are always good labels
1308 pDecodedItem->label.string = LabelItem.val.string;
1309 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1310 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001311 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001312 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1313 goto Done;
1314 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1315 pDecodedItem->label.int64 = LabelItem.val.int64;
1316 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1317 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1318 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1319 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1320 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1321 pDecodedItem->label.string = LabelItem.val.string;
1322 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1323 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1324 } else {
1325 // label is not an int or a string. It is an arrray
1326 // or a float or such and this implementation doesn't handle that.
1327 // Also, tags on labels are ignored.
1328 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1329 goto Done;
1330 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001331 }
1332 } else {
1333 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001334 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001335 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001336 goto Done;
1337 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001338 // Decoding a map as an array
1339 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001340 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1341 // Cast is needed because of integer promotion
1342 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001343 }
1344 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001345
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001346Done:
1347 return nReturn;
1348}
1349
1350
Laurence Lundblade02625d42020-06-25 14:41:41 -07001351/*
1352 See if next item is a CBOR break. If it is, it is consumed,
1353 if not it is not consumed.
1354*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001355static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001356NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1357{
1358 *pbNextIsBreak = false;
1359 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001360 QCBORItem Peek;
1361 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1362 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1363 if(uReturn != QCBOR_SUCCESS) {
1364 return uReturn;
1365 }
1366 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001367 // It is not a break, rewind so it can be processed normally.
1368 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001369 } else {
1370 *pbNextIsBreak = true;
1371 }
1372 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001373
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001374 return QCBOR_SUCCESS;
1375}
1376
1377
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001378/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001379 An item was just consumed, now figure out if it was the
1380 end of an array or map that can be closed out. That
1381 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001382*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001383static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001384{
1385 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001386
Laurence Lundblade642282a2020-06-23 12:00:33 -07001387 /* This loops ascending nesting levels as long as there is ascending to do */
1388 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1389
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001390 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001391 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001392 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1393 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001394 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001395 break;
1396 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07001397 /* All of a definite length array was consumed; fall through to
1398 ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001399
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001400 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001401 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001402 bool bIsBreak = false;
1403 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1404 if(uReturn != QCBOR_SUCCESS) {
1405 goto Done;
1406 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001407
1408 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001409 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001410 break;
1411 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001412
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001413 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001414 /*
1415 Break occurred inside a bstr-wrapped CBOR or
1416 in the top level sequence. This is always an
1417 error because neither are an indefinte length
1418 map/array.
1419 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001420 uReturn = QCBOR_ERR_BAD_BREAK;
1421 goto Done;
1422 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001423
Laurence Lundblade02625d42020-06-25 14:41:41 -07001424 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001425 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001426
Laurence Lundblade02625d42020-06-25 14:41:41 -07001427 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001428
Laurence Lundblade93d89472020-10-03 22:30:50 -07001429 /* But ascent in bounded mode is only by explicit call to
1430 QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001431 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001432 /* Set the count to zero for definite length arrays to indicate
1433 cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001434 if(bMarkEnd) {
1435 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001436 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001437
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001438 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001439 break;
1440 }
1441
1442 /* Finally, actually ascend one level. */
1443 DecodeNesting_Ascend(&(pMe->nesting));
1444 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001445
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001446 uReturn = QCBOR_SUCCESS;
1447
1448Done:
1449 return uReturn;
1450}
1451
1452
1453/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001454 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001455 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1456 indefinte length maps and arrays by looking at the item count or
1457 finding CBOR breaks. It detects the ends of the top-level sequence
1458 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001459
1460 @retval QCBOR_ERR_UNSUPPORTED X
1461
1462 @retval QCBOR_ERR_HIT_END
1463
1464 @retval QCBOR_ERR_INT_OVERFLOW X
1465
1466 @retval QCBOR_ERR_STRING_ALLOCATE
1467
1468 @retval QCBOR_ERR_STRING_TOO_LONG
1469
1470 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1471
1472 @retval QCBOR_ERR_BAD_TYPE_7 X
1473
1474 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1475
1476 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1477
1478 @retval QCBOR_ERR_TOO_MANY_TAGS
1479
1480 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1481
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001482 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001483
1484 @retval QCBOR_ERR_NO_MORE_ITEMS
1485
1486 @retval QCBOR_ERR_BAD_BREAK
1487
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001488 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001489static QCBORError
1490QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001491{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001492 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001493 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001494
Laurence Lundblade642282a2020-06-23 12:00:33 -07001495 /*
1496 If out of bytes to consume, it is either the end of the top-level
1497 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001498
Laurence Lundblade642282a2020-06-23 12:00:33 -07001499 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1500 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1501 CBOR is exited, the length is set back to the top-level's length
1502 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001503 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001504 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001505 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001506 goto Done;
1507 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001508
Laurence Lundblade642282a2020-06-23 12:00:33 -07001509 /*
1510 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001511 array. The check for the end of an indefinite length array is
1512 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001513 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001514 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001515 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001516 goto Done;
1517 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001518
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001519 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001520 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001521 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1522 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001523 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001524 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301525
Laurence Lundblade642282a2020-06-23 12:00:33 -07001526 /*
1527 Breaks ending arrays/maps are always processed at the end of this
1528 function. They should never show up here.
1529 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301530 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001531 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301532 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301533 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001534
Laurence Lundblade642282a2020-06-23 12:00:33 -07001535 /*
1536 Record the nesting level for this data item before processing any
1537 of decrementing and descending.
1538 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001539 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001540
Laurence Lundblade642282a2020-06-23 12:00:33 -07001541
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001542 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001543 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001544 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001545 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001546
Laurence Lundblade93d89472020-10-03 22:30:50 -07001547 Empty indefinite length maps and arrays are descended into, but
1548 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001549
1550 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001551 encloses them so a decrement needs to be done for them too, but
1552 that is done only when all the items in them have been
1553 processed, not when they are opened with the exception of an
1554 empty map or array.
1555 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001556 QCBORError uDescendErr;
1557 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001558 pDecodedItem->uDataType,
1559 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001560 if(uDescendErr != QCBOR_SUCCESS) {
1561 /* This error is probably a traversal error and it
1562 overrides the non-traversal error. */
1563 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001564 goto Done;
1565 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001566 }
1567
Laurence Lundblade02625d42020-06-25 14:41:41 -07001568 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1569 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1570 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001571 /*
1572 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001573 - A non-aggregate like an integer or string
1574 - An empty definite length map or array
1575 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001576
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001577 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001578 definite length map/array and break detection for an indefinite
1579 length map/array. If the end of the map/array was reached, then
1580 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001581 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001582 QCBORError uAscendErr;
1583 uAscendErr = NestLevelAscender(me, true);
1584 if(uAscendErr != QCBOR_SUCCESS) {
1585 /* This error is probably a traversal error and it
1586 overrides the non-traversal error. */
1587 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001588 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001589 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301590 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001591
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001592 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001593 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001594 Tell the caller what level is next. This tells them what
1595 maps/arrays were closed out and makes it possible for them to
1596 reconstruct the tree with just the information returned in
1597 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001598 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001599 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001600 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001601 pDecodedItem->uNextNestLevel = 0;
1602 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001603 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001604 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001605
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001606Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001607 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001608}
1609
Laurence Lundblade9b334962020-08-27 10:55:53 -07001610static void ShiftTags(QCBORItem *pDecodedItem)
1611{
1612 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1613 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1614 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1615 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1616}
1617
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001618
Laurence Lundblade59289e52019-12-30 13:44:37 -08001619/*
1620 Mostly just assign the right data type for the date string.
1621 */
1622inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1623{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001624 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1625 return QCBOR_ERR_BAD_OPT_TAG;
1626 }
1627
1628 const UsefulBufC Temp = pDecodedItem->val.string;
1629 pDecodedItem->val.dateString = Temp;
1630 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001631 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001632 return QCBOR_SUCCESS;
1633}
1634
1635
Laurence Lundblade9b334962020-08-27 10:55:53 -07001636
Laurence Lundblade59289e52019-12-30 13:44:37 -08001637/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001638 The epoch formatted date. Turns lots of different forms of encoding
1639 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001640 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001641static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001642{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001643 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001644
1645 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1646
1647 switch (pDecodedItem->uDataType) {
1648
1649 case QCBOR_TYPE_INT64:
1650 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1651 break;
1652
1653 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001654 // This only happens for CBOR type 0 > INT64_MAX so it is
1655 // always an overflow.
1656 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1657 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001658 break;
1659
1660 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001661 case QCBOR_TYPE_FLOAT:
1662#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001663 {
1664 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001665 // conversion to an int64_t to be able to detect doubles that
1666 // are too large to fit into an int64_t. A double has 52
1667 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1668 // to a double actually causes a round up which is bad and
1669 // wrong for the comparison because it will allow conversion
1670 // of doubles that can't fit into a uint64_t. To remedy this
1671 // INT64_MAX - 0x7ff is used as the cutoff point because if
1672 // that value rounds up in conversion to double it will still
1673 // be less than INT64_MAX. 0x7ff is picked because it has 11
1674 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001675 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001676 // INT64_MAX seconds is on the order of 10 billion years, and
1677 // the earth is less than 5 billion years old, so for most
1678 // uses this conversion error won't occur even though doubles
1679 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001680 //
1681 // Without the 0x7ff there is a ~30 minute range of time
1682 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001683 // where this code would go wrong. Some compilers
1684 // will generate warnings or errors without the 0x7ff
1685 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001686 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1687 pDecodedItem->val.dfnum :
1688 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001689 if(isnan(d) ||
1690 d > (double)(INT64_MAX - 0x7ff) ||
1691 d < (double)(INT64_MIN + 0x7ff)) {
1692 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001693 goto Done;
1694 }
1695 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001696 pDecodedItem->val.epochDate.fSecondsFraction =
1697 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001698 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001699#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001700
Laurence Lundbladec7114722020-08-13 05:11:40 -07001701 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001702 goto Done;
1703
Laurence Lundblade9682a532020-06-06 18:33:04 -07001704#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001705 break;
1706
1707 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001708 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001709 goto Done;
1710 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001711
Laurence Lundblade59289e52019-12-30 13:44:37 -08001712 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1713
1714Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001715 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001716}
1717
1718
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001719/*
1720 Mostly just assign the right data type for the bignum.
1721 */
1722inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1723{
1724 // Stack Use: UsefulBuf 1 -- 16
1725 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1726 return QCBOR_ERR_BAD_OPT_TAG;
1727 }
1728 const UsefulBufC Temp = pDecodedItem->val.string;
1729 pDecodedItem->val.bigNum = Temp;
1730 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1731 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1732 : QCBOR_TYPE_NEGBIGNUM);
1733 return QCBOR_SUCCESS;
1734}
1735
1736
Laurence Lundblade59289e52019-12-30 13:44:37 -08001737#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1738/*
1739 Decode decimal fractions and big floats.
1740
1741 When called pDecodedItem must be the array that is tagged as a big
1742 float or decimal fraction, the array that has the two members, the
1743 exponent and mantissa.
1744
1745 This will fetch and decode the exponent and mantissa and put the
1746 result back into pDecodedItem.
1747 */
1748inline static QCBORError
1749QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1750{
1751 QCBORError nReturn;
1752
1753 // --- Make sure it is an array; track nesting level of members ---
1754 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1755 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1756 goto Done;
1757 }
1758
1759 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001760 // definite length arrays, but not for indefnite. Instead remember
1761 // the nesting level the two integers must be at, which is one
1762 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001763 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1764
1765 // --- Is it a decimal fraction or a bigfloat? ---
1766 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1767 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1768
1769 // --- Get the exponent ---
1770 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001771 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001772 if(nReturn != QCBOR_SUCCESS) {
1773 goto Done;
1774 }
1775 if(exponentItem.uNestingLevel != nNestLevel) {
1776 // Array is empty or a map/array encountered when expecting an int
1777 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1778 goto Done;
1779 }
1780 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1781 // Data arriving as an unsigned int < INT64_MAX has been converted
1782 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1783 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1784 // will be too large for this to handle and thus an error that will
1785 // get handled in the next else.
1786 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1787 } else {
1788 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1789 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1790 goto Done;
1791 }
1792
1793 // --- Get the mantissa ---
1794 QCBORItem mantissaItem;
1795 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1796 if(nReturn != QCBOR_SUCCESS) {
1797 goto Done;
1798 }
1799 if(mantissaItem.uNestingLevel != nNestLevel) {
1800 // Mantissa missing or map/array encountered when expecting number
1801 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1802 goto Done;
1803 }
1804 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1805 // Data arriving as an unsigned int < INT64_MAX has been converted
1806 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1807 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1808 // will be too large for this to handle and thus an error that
1809 // will get handled in an else below.
1810 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001811 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1812 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001813 // Got a good big num mantissa
1814 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1815 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001816 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1817 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1818 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001819 } else {
1820 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1821 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1822 goto Done;
1823 }
1824
1825 // --- Check that array only has the two numbers ---
1826 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001827 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001828 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1829 goto Done;
1830 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001831 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001832
1833Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001834 return nReturn;
1835}
1836#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1837
1838
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001839inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1840{
1841 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1842 return QCBOR_ERR_BAD_OPT_TAG;
1843 }
1844 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1845 return QCBOR_SUCCESS;
1846}
1847
1848
1849inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1850{
1851 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1852 return QCBOR_ERR_BAD_OPT_TAG;
1853 }
1854 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001855
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001856 return QCBOR_SUCCESS;
1857}
1858
1859
1860inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1861{
1862 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1863 return QCBOR_ERR_BAD_OPT_TAG;
1864 }
1865 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001866
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001867 return QCBOR_SUCCESS;
1868}
1869
1870
1871inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1872{
1873 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1874 return QCBOR_ERR_BAD_OPT_TAG;
1875 }
1876 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001877
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001878 return QCBOR_SUCCESS;
1879}
1880
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001881
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001882inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1883{
1884 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1885 return QCBOR_ERR_BAD_OPT_TAG;
1886 }
1887 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001888
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001889 return QCBOR_SUCCESS;
1890}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001891
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001892
1893inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1894{
1895 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1896 return QCBOR_ERR_BAD_OPT_TAG;
1897 }
1898 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001899
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001900 return QCBOR_SUCCESS;
1901}
1902
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001903
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001904inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1905{
1906 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1907 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001908 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001909 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1910 } else {
1911 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001912
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001913 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001914
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001915 return QCBOR_SUCCESS;
1916}
1917
1918
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001919inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1920{
1921 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1922 return QCBOR_ERR_BAD_OPT_TAG;
1923 }
1924 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001925
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001926 return QCBOR_SUCCESS;
1927}
1928
1929
Laurence Lundblade59289e52019-12-30 13:44:37 -08001930/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001931 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001932 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001933static QCBORError
1934QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001935{
1936 QCBORError nReturn;
1937
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001938 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001939 if(nReturn != QCBOR_SUCCESS) {
1940 goto Done;
1941 }
1942
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001943 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001944 switch(pDecodedItem->uTags[i]) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001945
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001946 // Many of the functions here only just map a CBOR tag to
1947 // a QCBOR_TYPE for a string and could probably be
1948 // implemented with less object code. This implementation
1949 // of string types takes about 120 bytes of object code
1950 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001951 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001952 nReturn = DecodeDateString(pDecodedItem);
1953 break;
1954
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001955 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001956 nReturn = DecodeDateEpoch(pDecodedItem);
1957 break;
1958
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001959 case CBOR_TAG_POS_BIGNUM:
1960 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001961 nReturn = DecodeBigNum(pDecodedItem);
1962 break;
1963
Laurence Lundblade93d89472020-10-03 22:30:50 -07001964#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001965 case CBOR_TAG_DECIMAL_FRACTION:
1966 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001967 // For aggregate tagged types, what goes into pTags is only collected
1968 // from the surrounding data item, not the contents, so pTags is not
1969 // passed on here.
1970
1971 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1972 break;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001973#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001974
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001975 case CBOR_TAG_CBOR:
1976 nReturn = DecodeWrappedCBOR(pDecodedItem);
1977 break;
1978
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001979 case CBOR_TAG_CBOR_SEQUENCE:
1980 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1981 break;
1982
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001983 case CBOR_TAG_URI:
1984 nReturn = DecodeURI(pDecodedItem);
1985 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001986
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001987 case CBOR_TAG_B64URL:
1988 nReturn = DecodeB64URL(pDecodedItem);
1989 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001990
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001991 case CBOR_TAG_B64:
1992 nReturn = DecodeB64(pDecodedItem);
1993 break;
1994
1995 case CBOR_TAG_MIME:
1996 case CBOR_TAG_BINARY_MIME:
1997 nReturn = DecodeMIME(pDecodedItem);
1998 break;
1999
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002000 case CBOR_TAG_REGEX:
2001 nReturn = DecodeRegex(pDecodedItem);
2002 break;
2003
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002004 case CBOR_TAG_BIN_UUID:
2005 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002006 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002007
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002008 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002009 // The end of the tag list or no tags
2010 // Successful exit from the loop.
2011 goto Done;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002012
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002013 default:
2014 // A tag that is not understood
2015 // A successful exit from the loop
2016 goto Done;
2017
2018 }
2019 if(nReturn != QCBOR_SUCCESS) {
2020 goto Done;
2021 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002022 // A tag was successfully processed, shift it
2023 // out of the list of tags returned.
2024 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002025 }
2026
2027Done:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002028 return nReturn;
2029}
2030
2031
2032QCBORError
2033QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2034{
2035 QCBORError uErr;
2036 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2037 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002038 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2039 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2040 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002041 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002042}
2043
2044
2045/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002046 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002047 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002048void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2049{
2050 if(pMe->uLastError != QCBOR_SUCCESS) {
2051 return;
2052 }
2053
2054 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2055}
2056
2057
2058/*
2059 Public function, see header qcbor/qcbor_decode.h file
2060 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002061QCBORError
2062QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2063 QCBORItem *pDecodedItem,
2064 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002065{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002066 QCBORError nReturn;
2067
2068 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2069 if(nReturn != QCBOR_SUCCESS) {
2070 return nReturn;
2071 }
2072
2073 if(pTags != NULL) {
2074 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002075 // Reverse the order because pTags is reverse of
2076 // QCBORItem.uTags.
2077 for(int i = QCBOR_MAX_TAGS_PER_ITEM-1; i >=0 ; i--) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002078 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002079 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002080 }
2081 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2082 return QCBOR_ERR_TOO_MANY_TAGS;
2083 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07002084 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[i]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002085 pTags->uNumUsed++;
2086 }
2087 }
2088
2089 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002090}
2091
2092
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002093/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302094 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302095 next one down. If a layer has no work to do for a particular item
2096 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002097
Laurence Lundblade59289e52019-12-30 13:44:37 -08002098 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2099 tagged data items, turning them into the local C representation.
2100 For the most simple it is just associating a QCBOR_TYPE with the data. For
2101 the complex ones that an aggregate of data items, there is some further
2102 decoding and a little bit of recursion.
2103
2104 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302105 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302106 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002107 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002108
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302109 - GetNext_MapEntry -- This handles the combining of two
2110 items, the label and the data, that make up a map entry.
2111 It only does work on maps. It combines the label and data
2112 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002113
Laurence Lundblade59289e52019-12-30 13:44:37 -08002114 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2115 tags into bit flags associated with the data item. No actual decoding
2116 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002117
Laurence Lundblade59289e52019-12-30 13:44:37 -08002118 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302119 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302120 string allocater to create contiguous space for the item. It
2121 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002122
Laurence Lundblade59289e52019-12-30 13:44:37 -08002123 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2124 atomic data item has a "major type", an integer "argument" and optionally
2125 some content. For text and byte strings, the content is the bytes
2126 that make up the string. These are the smallest data items that are
2127 considered to be well-formed. The content may also be other data items in
2128 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002129
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002130 Roughly this takes 300 bytes of stack for vars. Need to
2131 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002132
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302133 */
2134
2135
2136/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002137 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002138 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002139bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002140 const QCBORItem *pItem,
2141 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002142{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002143 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002144 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002145 break;
2146 }
2147 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002148 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002149 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002150 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002151
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002152 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002153}
2154
2155
2156/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002157 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002158 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002159QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002160{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002161 QCBORError uReturn = me->uLastError;
2162
2163 if(uReturn != QCBOR_SUCCESS) {
2164 goto Done;
2165 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002166
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002167 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002168 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002169 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002170 goto Done;
2171 }
2172
2173 // Error out if not all the bytes are consumed
2174 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002175 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002176 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002177
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002178Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302179 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002180 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002181 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002182
Laurence Lundblade085d7952020-07-24 10:26:30 -07002183 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002184}
2185
2186
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002187/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002188 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002189*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002190// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002191uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2192 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002193 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002194{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002195 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2196 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002197 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002198 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002199 }
2200}
2201
Laurence Lundblade9b334962020-08-27 10:55:53 -07002202/*
2203 Public function, see header qcbor/qcbor_decode.h file
2204*/
2205uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2206 uint32_t uIndex)
2207{
2208 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2209 return CBOR_TAG_INVALID64;
2210 } else {
2211 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2212 }
2213}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002214
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002215/*
2216
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002217Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002218
Laurence Lundbladeee851742020-01-08 08:37:05 -08002219 - Hit end of input before it was expected while decoding type and
2220 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002221
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002222 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002223
Laurence Lundbladeee851742020-01-08 08:37:05 -08002224 - Hit end of input while decoding a text or byte string
2225 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002226
Laurence Lundbladeee851742020-01-08 08:37:05 -08002227 - Encountered conflicting tags -- e.g., an item is tagged both a date
2228 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002229
Laurence Lundbladeee851742020-01-08 08:37:05 -08002230 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002231 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002232
Laurence Lundbladeee851742020-01-08 08:37:05 -08002233 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002234 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002235
Laurence Lundbladeee851742020-01-08 08:37:05 -08002236 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2237 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002238
Laurence Lundbladeee851742020-01-08 08:37:05 -08002239 - The type of a map label is not a string or int
2240 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002241
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002242 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002243
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002244 */
2245
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002246
2247
Laurence Lundbladef6531662018-12-04 10:42:22 +09002248
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002249/* ===========================================================================
2250 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002251
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002252 This implements a simple sting allocator for indefinite length
2253 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2254 implements the function type QCBORStringAllocate and allows easy
2255 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002256
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002257 This particular allocator is built-in for convenience. The caller
2258 can implement their own. All of this following code will get
2259 dead-stripped if QCBORDecode_SetMemPool() is not called.
2260
2261 This is a very primitive memory allocator. It does not track
2262 individual allocations, only a high-water mark. A free or
2263 reallocation must be of the last chunk allocated.
2264
2265 The size of the pool and offset to free memory are packed into the
2266 first 8 bytes of the memory pool so we don't have to keep them in
2267 the decode context. Since the address of the pool may not be
2268 aligned, they have to be packed and unpacked as if they were
2269 serialized data of the wire or such.
2270
2271 The sizes packed in are uint32_t to be the same on all CPU types
2272 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002273 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002274
2275
Laurence Lundbladeee851742020-01-08 08:37:05 -08002276static inline int
2277MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002278{
2279 // Use of UsefulInputBuf is overkill, but it is convenient.
2280 UsefulInputBuf UIB;
2281
Laurence Lundbladeee851742020-01-08 08:37:05 -08002282 // Just assume the size here. It was checked during SetUp so
2283 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002284 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002285 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2286 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2287 return UsefulInputBuf_GetError(&UIB);
2288}
2289
2290
Laurence Lundbladeee851742020-01-08 08:37:05 -08002291static inline int
2292MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002293{
2294 // Use of UsefulOutBuf is overkill, but convenient. The
2295 // length check performed here is useful.
2296 UsefulOutBuf UOB;
2297
2298 UsefulOutBuf_Init(&UOB, Pool);
2299 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2300 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2301 return UsefulOutBuf_GetError(&UOB);
2302}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002303
2304
2305/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002306 Internal function for an allocation, reallocation free and destuct.
2307
2308 Having only one function rather than one each per mode saves space in
2309 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002310
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002311 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2312 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002313static UsefulBuf
2314MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002315{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002316 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002317
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002318 uint32_t uPoolSize;
2319 uint32_t uFreeOffset;
2320
2321 if(uNewSize > UINT32_MAX) {
2322 // This allocator is only good up to 4GB. This check should
2323 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2324 goto Done;
2325 }
2326 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2327
2328 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2329 goto Done;
2330 }
2331
2332 if(uNewSize) {
2333 if(pMem) {
2334 // REALLOCATION MODE
2335 // Calculate pointer to the end of the memory pool. It is
2336 // assumed that pPool + uPoolSize won't wrap around by
2337 // assuming the caller won't pass a pool buffer in that is
2338 // not in legitimate memory space.
2339 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2340
2341 // Check that the pointer for reallocation is in the range of the
2342 // pool. This also makes sure that pointer math further down
2343 // doesn't wrap under or over.
2344 if(pMem >= pPool && pMem < pPoolEnd) {
2345 // Offset to start of chunk for reallocation. This won't
2346 // wrap under because of check that pMem >= pPool. Cast
2347 // is safe because the pool is always less than UINT32_MAX
2348 // because of check in QCBORDecode_SetMemPool().
2349 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2350
2351 // Check to see if the allocation will fit. uPoolSize -
2352 // uMemOffset will not wrap under because of check that
2353 // pMem is in the range of the uPoolSize by check above.
2354 if(uNewSize <= uPoolSize - uMemOffset) {
2355 ReturnValue.ptr = pMem;
2356 ReturnValue.len = uNewSize;
2357
2358 // Addition won't wrap around over because uNewSize was
2359 // checked to be sure it is less than the pool size.
2360 uFreeOffset = uMemOffset + uNewSize32;
2361 }
2362 }
2363 } else {
2364 // ALLOCATION MODE
2365 // uPoolSize - uFreeOffset will not underflow because this
2366 // pool implementation makes sure uFreeOffset is always
2367 // smaller than uPoolSize through this check here and
2368 // reallocation case.
2369 if(uNewSize <= uPoolSize - uFreeOffset) {
2370 ReturnValue.len = uNewSize;
2371 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002372 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002373 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002374 }
2375 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002376 if(pMem) {
2377 // FREE MODE
2378 // Cast is safe because of limit on pool size in
2379 // QCBORDecode_SetMemPool()
2380 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2381 } else {
2382 // DESTRUCT MODE
2383 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002384 }
2385 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002386
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002387 UsefulBuf Pool = {pPool, uPoolSize};
2388 MemPool_Pack(Pool, uFreeOffset);
2389
2390Done:
2391 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002392}
2393
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002394
Laurence Lundbladef6531662018-12-04 10:42:22 +09002395/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002396 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002397 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002398QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2399 UsefulBuf Pool,
2400 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002401{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002402 // The pool size and free mem offset are packed into the beginning
2403 // of the pool memory. This compile time check make sure the
2404 // constant in the header is correct. This check should optimize
2405 // down to nothing.
2406 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002407 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002408 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002409
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002410 // The pool size and free offset packed in to the beginning of pool
2411 // memory are only 32-bits. This check will optimize out on 32-bit
2412 // machines.
2413 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002414 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002415 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002416
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002417 // This checks that the pool buffer given is big enough.
2418 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002419 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002420 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002421
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002422 pMe->StringAllocator.pfAllocator = MemPool_Function;
2423 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2424 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002425
Laurence Lundblade30816f22018-11-10 13:40:22 +07002426 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002427}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002428
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002429
2430
Laurence Lundblade9b334962020-08-27 10:55:53 -07002431static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2432{
2433 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2434}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002435
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002436
2437/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002438 Consume an entire map or array (and do next to
2439 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002440 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002441static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002442ConsumeItem(QCBORDecodeContext *pMe,
2443 const QCBORItem *pItemToConsume,
2444 uint_fast8_t *puNextNestLevel)
2445{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002446 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002447 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002448
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002449 // If it is a map or array, this will tell if it is empty.
2450 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2451
2452 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2453 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002454
Laurence Lundblade1341c592020-04-11 14:19:05 -07002455 /* This works for definite and indefinite length
2456 * maps and arrays by using the nesting level
2457 */
2458 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002459 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002460 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002461 goto Done;
2462 }
2463 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002464
Laurence Lundblade1341c592020-04-11 14:19:05 -07002465 if(puNextNestLevel != NULL) {
2466 *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 Lundblade1341c592020-04-11 14:19:05 -07002472 if(puNextNestLevel != NULL) {
2473 /* Just pass the nesting level through */
2474 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2475 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002476 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002477 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002478
2479Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002480 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002481}
2482
2483
Laurence Lundblade1341c592020-04-11 14:19:05 -07002484/* Return true if the labels in Item1 and Item2 are the same.
2485 Works only for integer and string labels. Returns false
2486 for any other type. */
2487static inline bool
2488MatchLabel(QCBORItem Item1, QCBORItem Item2)
2489{
2490 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2491 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2492 return true;
2493 }
2494 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002495 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002496 return true;
2497 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002498 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002499 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2500 return true;
2501 }
2502 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2503 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2504 return true;
2505 }
2506 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002507
Laurence Lundblade1341c592020-04-11 14:19:05 -07002508 /* Other label types are never matched */
2509 return false;
2510}
2511
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002512
2513/*
2514 Returns true if Item1 and Item2 are the same type
2515 or if either are of QCBOR_TYPE_ANY.
2516 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002517static inline bool
2518MatchType(QCBORItem Item1, QCBORItem Item2)
2519{
2520 if(Item1.uDataType == Item2.uDataType) {
2521 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002522 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002523 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002524 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002525 return true;
2526 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002527 return false;
2528}
2529
2530
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002531/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002532 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002533
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002534 @param[in] pMe The decode context to search.
2535 @param[in,out] pItemArray The items to search for and the items found.
2536 @param[out] puOffset Byte offset of last item matched.
2537 @param[in] pCBContext Context for the not-found item call back.
2538 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002539
2540 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2541
Laurence Lundblade93d89472020-10-03 22:30:50 -07002542 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2543 were found for one of the labels being
2544 search for. This duplicate detection is
2545 only performed for items in pItemArray,
2546 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002547
Laurence Lundblade93d89472020-10-03 22:30:50 -07002548 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2549 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002550
2551 @retval Also errors returned by QCBORDecode_GetNext().
2552
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002553 On input pItemArray contains a list of labels and data types
2554 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002555
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002556 On output the fully retrieved items are filled in with
2557 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002558
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002559 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002560 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002561static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002562MapSearch(QCBORDecodeContext *pMe,
2563 QCBORItem *pItemArray,
2564 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002565 void *pCBContext,
2566 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002567{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002568 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002569 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002570
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002571 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002572 uReturn = pMe->uLastError;
2573 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002574 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002575
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002576 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002577 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2578 /* QCBOR_TYPE_NONE as first item indicates just looking
2579 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002580 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2581 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002582 }
2583
Laurence Lundblade085d7952020-07-24 10:26:30 -07002584 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2585 // It is an empty bounded array or map
2586 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2587 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002588 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002589 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002590 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002591 // Nothing is ever found in an empty array or map. All items
2592 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002593 uReturn = QCBOR_SUCCESS;
2594 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002595 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002596 }
2597
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002598 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002599 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2600
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002601 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002602 UsefulInputBuf_Seek(&(pMe->InBuf),
2603 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002604
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002605 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002606 Loop over all the items in the map or array. Each item
2607 could be a map or array, but label matching is only at
2608 the main level. This handles definite and indefinite
2609 length maps and arrays. The only reason this is ever
2610 called on arrays is to find their end position.
2611
2612 This will always run over all items in order to do
2613 duplicate detection.
2614
2615 This will exit with failure if it encounters an
2616 unrecoverable error, but continue on for recoverable
2617 errors.
2618
2619 If a recoverable error occurs on a matched item, then
2620 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002621 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002622 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002623 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002624 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002625 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002626 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002627
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002628 /* Get the item */
2629 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002630 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2631 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002632 /* Got non-well-formed CBOR so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002633 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002634 goto Done;
2635 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002636 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002637 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002638 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002639 goto Done;
2640 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002641
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002642 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002643 bool bMatched = false;
2644 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2645 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002646 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002647 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2648 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002649 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002650 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002651 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002652 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002653 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002654 goto Done;
2655 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002656
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002657 if(uResult != QCBOR_SUCCESS) {
2658 uReturn = uResult;
2659 goto Done;
2660 }
2661
Laurence Lundblade1341c592020-04-11 14:19:05 -07002662 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002663 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002664 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002665 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002666 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002667 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002668 bMatched = true;
2669 }
2670 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002671
2672
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002673 if(!bMatched && pfCallback != NULL) {
2674 /*
2675 Call the callback on unmatched labels.
2676 (It is tempting to do duplicate detection here, but that would
2677 require dynamic memory allocation because the number of labels
2678 that might be encountered is unbounded.)
2679 */
2680 uReturn = (*pfCallback)(pCBContext, &Item);
2681 if(uReturn != QCBOR_SUCCESS) {
2682 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002683 }
2684 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002685
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002686 /*
2687 Consume the item whether matched or not. This
2688 does the work of traversing maps and array and
2689 everything in them. In this loop only the
2690 items at the current nesting level are examined
2691 to match the labels.
2692 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002693 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002694 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002695 goto Done;
2696 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002697
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002698 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002699
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002700 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002701
2702 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002703
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002704 // Check here makes sure that this won't accidentally be
2705 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002706 // QCBOR_MAX_DECODE_INPUT_SIZE.
2707 if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
2708 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2709 goto Done;
2710 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002711 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2712 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002713
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002714 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002715 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2716
2717 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002718 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002719 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002720 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002721 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2722 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002723 }
2724 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002725
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002726 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002727}
2728
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002729
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002730/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002731 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002732*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002733void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2734 int64_t nLabel,
2735 uint8_t uQcborType,
2736 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002737{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002738 if(pMe->uLastError != QCBOR_SUCCESS) {
2739 return;
2740 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002741
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002742 QCBORItem OneItemSeach[2];
2743 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2744 OneItemSeach[0].label.int64 = nLabel;
2745 OneItemSeach[0].uDataType = uQcborType;
2746 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002747
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002748 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002749
2750 *pItem = OneItemSeach[0];
2751
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002752 if(uReturn != QCBOR_SUCCESS) {
2753 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002754 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002755 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002756 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002757 }
2758
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002759 Done:
2760 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002761}
2762
2763
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002764/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002765 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002766*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002767void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2768 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002769 uint8_t uQcborType,
2770 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002771{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002772 if(pMe->uLastError != QCBOR_SUCCESS) {
2773 return;
2774 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002775
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002776 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002777 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2778 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2779 OneItemSeach[0].uDataType = uQcborType;
2780 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002781
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002782 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2783 if(uReturn != QCBOR_SUCCESS) {
2784 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002785 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002786 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002787 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002788 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002789 }
2790
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002791 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002792
2793Done:
2794 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002795}
2796
2797
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002798
Laurence Lundblade93d89472020-10-03 22:30:50 -07002799static QCBORError
2800CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002801{
2802 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2803 if(uDataType == puTypeList[i]) {
2804 return QCBOR_SUCCESS;
2805 }
2806 }
2807 return QCBOR_ERR_UNEXPECTED_TYPE;
2808}
2809
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002810
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002811/**
2812 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002813 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002814
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002815 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2816 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002817
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002818 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2819 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002820static QCBORError
2821CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002822{
2823 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2824 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2825 /* There are tags that QCBOR couldn't process on this item and
2826 the caller has told us there should not be. */
2827 return QCBOR_ERR_UNEXPECTED_TYPE;
2828 }
2829
2830 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2831 const int nItemType = pItem->uDataType;
2832
2833 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2834 // Must match the tag and only the tag
2835 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2836 }
2837
2838 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2839 if(uReturn == QCBOR_SUCCESS) {
2840 return QCBOR_SUCCESS;
2841 }
2842
2843 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2844 /* Must match the content type and only the content type.
2845 There was no match just above so it is a fail. */
2846 return QCBOR_ERR_UNEXPECTED_TYPE;
2847 }
2848
2849 /* If here it can match either the tag or the content
2850 and it hasn't matched the content, so the end
2851 result is whether it matches the tag. This is
2852 also the case that the CBOR standard discourages. */
2853
2854 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2855}
2856
Laurence Lundblade9b334962020-08-27 10:55:53 -07002857
Laurence Lundblade9b334962020-08-27 10:55:53 -07002858
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002859// This could be semi-private if need be
2860static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002861void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2862 int64_t nLabel,
2863 TagSpecification TagSpec,
2864 QCBORItem *pItem)
2865{
2866 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2867 if(pMe->uLastError != QCBOR_SUCCESS) {
2868 return;
2869 }
2870
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002871 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002872}
2873
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002874
2875// This could be semi-private if need be
2876static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002877void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2878 const char *szLabel,
2879 TagSpecification TagSpec,
2880 QCBORItem *pItem)
2881{
2882 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2883 if(pMe->uLastError != QCBOR_SUCCESS) {
2884 return;
2885 }
2886
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002887 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002888}
2889
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002890// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002891void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2892 int64_t nLabel,
2893 TagSpecification TagSpec,
2894 UsefulBufC *pString)
2895{
2896 QCBORItem Item;
2897 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2898 if(pMe->uLastError == QCBOR_SUCCESS) {
2899 *pString = Item.val.string;
2900 }
2901}
2902
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002903// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002904void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2905 const char * szLabel,
2906 TagSpecification TagSpec,
2907 UsefulBufC *pString)
2908{
2909 QCBORItem Item;
2910 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2911 if(pMe->uLastError == QCBOR_SUCCESS) {
2912 *pString = Item.val.string;
2913 }
2914}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002915
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002916/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002917 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002918*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002919void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002920{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002921 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2922 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002923}
2924
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002925/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002926 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002927*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002928void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2929 QCBORItem *pItemList,
2930 void *pCallbackCtx,
2931 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002932{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002933 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2934 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002935}
2936
2937
Laurence Lundblade34691b92020-05-18 22:25:25 -07002938static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002939{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002940 // The first item in pSearch is the one that is to be
2941 // entered. It should be the only one filled in. Any other
2942 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07002943 if(pMe->uLastError != QCBOR_SUCCESS) {
2944 // Already in error state; do nothing.
2945 return;
2946 }
2947
2948 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002949 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002950 if(pMe->uLastError != QCBOR_SUCCESS) {
2951 return;
2952 }
2953
Laurence Lundblade9b334962020-08-27 10:55:53 -07002954 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002955 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002956 return;
2957 }
2958
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002959 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002960 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002961
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002962 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002963 be at the right place.
2964
2965 The UsefulInBuf offset could be anywhere, so no assumption is
2966 made about it.
2967
2968 No assumption is made about the pre-order nesting level either.
2969
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002970 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002971 the map level that is being entered.
2972 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002973 /* Seek to the data item that is the map or array */
2974 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002975
2976 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002977
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07002978 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002979}
2980
2981
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002982/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002983 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002984*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002985void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002986{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002987 QCBORItem OneItemSeach[2];
2988 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2989 OneItemSeach[0].label.int64 = nLabel;
2990 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2991 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002992
Laurence Lundblade9b334962020-08-27 10:55:53 -07002993 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002994 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002995}
2996
2997
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002998/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002999 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003000*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003001void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003002{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003003 QCBORItem OneItemSeach[2];
3004 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3005 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3006 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3007 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003008
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003009 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003010}
3011
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003012/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003013 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003014*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003015void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003016{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003017 QCBORItem OneItemSeach[2];
3018 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3019 OneItemSeach[0].label.int64 = nLabel;
3020 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3021 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003022
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003023 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003024}
3025
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003026/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003027 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003028*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003029void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3030{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003031 QCBORItem OneItemSeach[2];
3032 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3033 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3034 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3035 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003036
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003037 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003038}
3039
3040
Laurence Lundblade02625d42020-06-25 14:41:41 -07003041// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003042void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003043{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003044 QCBORError uErr;
3045
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003046 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003047 if(pMe->uLastError != QCBOR_SUCCESS) {
3048 // Already in error state; do nothing.
3049 return;
3050 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003051
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003052 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003053 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003054 uErr = QCBORDecode_GetNext(pMe, &Item);
3055 if(uErr != QCBOR_SUCCESS) {
3056 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003057 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003058 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003059 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3060 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003061 }
3062
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003063 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003064
3065
Laurence Lundbladef0499502020-08-01 11:55:57 -07003066 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003067 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003068 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3069 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003070 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003071 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3072 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003073 // Special case to increment nesting level for zero-length maps
3074 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003075 DecodeNesting_Descend(&(pMe->nesting), uType);
3076 }
3077
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003078 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003079
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003080 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3081 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003082
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003083 if(pItem != NULL) {
3084 *pItem = Item;
3085 }
3086
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003087Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003088 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003089}
3090
Laurence Lundblade02625d42020-06-25 14:41:41 -07003091
3092/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003093 This is the common work for exiting a level that is a bounded map,
3094 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003095
3096 One chunk of work is to set up the pre-order traversal so it is at
3097 the item just after the bounded map, array or bstr that is being
3098 exited. This is somewhat complex.
3099
3100 The other work is to level-up the bounded mode to next higest bounded
3101 mode or the top level if there isn't one.
3102 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003103static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003104ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003105{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003106 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003107
Laurence Lundblade02625d42020-06-25 14:41:41 -07003108 /*
3109 First the pre-order-traversal byte offset is positioned to the
3110 item just after the bounded mode item that was just consumed.
3111 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003112 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3113
Laurence Lundblade02625d42020-06-25 14:41:41 -07003114 /*
3115 Next, set the current nesting level to one above the bounded level
3116 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003117
Laurence Lundblade02625d42020-06-25 14:41:41 -07003118 DecodeNesting_CheckBoundedType() is always called before this and
3119 makes sure pCurrentBounded is valid.
3120 */
3121 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3122
3123 /*
3124 This does the complex work of leveling up the pre-order traversal
3125 when the end of a map or array or another bounded level is
3126 reached. It may do nothing, or ascend all the way to the top
3127 level.
3128 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003129 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003130 if(uErr != QCBOR_SUCCESS) {
3131 goto Done;
3132 }
3133
Laurence Lundblade02625d42020-06-25 14:41:41 -07003134 /*
3135 This makes the next highest bounded level the current bounded
3136 level. If there is no next highest level, then no bounded mode is
3137 in effect.
3138 */
3139 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003140
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003141 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003142
3143Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003144 return uErr;
3145}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003146
Laurence Lundblade02625d42020-06-25 14:41:41 -07003147
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003148// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003149void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003150{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003151 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003152 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003153 return;
3154 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003155
Laurence Lundblade02625d42020-06-25 14:41:41 -07003156 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003157
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003158 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003159 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003160 goto Done;
3161 }
3162
Laurence Lundblade02625d42020-06-25 14:41:41 -07003163 /*
3164 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003165 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003166 from previous map search, then do a dummy search.
3167 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003168 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003169 QCBORItem Dummy;
3170 Dummy.uLabelType = QCBOR_TYPE_NONE;
3171 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3172 if(uErr != QCBOR_SUCCESS) {
3173 goto Done;
3174 }
3175 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003176
Laurence Lundblade02625d42020-06-25 14:41:41 -07003177 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003178
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003179Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003180 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003181}
3182
3183
Laurence Lundblade1341c592020-04-11 14:19:05 -07003184
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003185static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003186 const QCBORItem *pItem,
3187 uint8_t uTagRequirement,
3188 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003189{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003190 if(pBstr) {
3191 *pBstr = NULLUsefulBufC;
3192 }
3193
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003194 if(pMe->uLastError != QCBOR_SUCCESS) {
3195 // Already in error state; do nothing.
3196 return pMe->uLastError;
3197 }
3198
3199 QCBORError uError = QCBOR_SUCCESS;
3200
3201 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3202 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3203 goto Done;;
3204 }
3205
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003206 const TagSpecification TagSpec =
3207 {
3208 uTagRequirement,
3209 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3210 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3211 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003212
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003213 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003214 if(uError != QCBOR_SUCCESS) {
3215 goto Done;
3216 }
3217
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003218 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003219 // Reverse the decrement done by GetNext() for the bstr so the
3220 // increment in NestLevelAscender() called by ExitBoundedLevel()
3221 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003222 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003223 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003224
3225 if(pBstr) {
3226 *pBstr = pItem->val.string;
3227 }
3228
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003229 // This saves the current length of the UsefulInputBuf and then
3230 // narrows the UsefulInputBuf to start and length of the wrapped
3231 // CBOR that is being entered.
3232 //
3233 // This makes sure the length is less than
3234 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3235 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3236 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3237 // the casts safe. uEndOfBstr will always be less than
3238 // uPreviousLength because of the way UsefulInputBuf works so there
3239 // is no need to check it. There is also a range check in the
3240 // seek.
3241 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003242 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003243 // amount to much code.
3244 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3245 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003246 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003247 goto Done;
3248 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003249 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003250 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003251 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003252
Laurence Lundblade02625d42020-06-25 14:41:41 -07003253 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003254 (uint32_t)uPreviousLength,
3255 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003256Done:
3257 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003258}
3259
3260
Laurence Lundblade02625d42020-06-25 14:41:41 -07003261/*
3262 Public function, see header qcbor/qcbor_decode.h file
3263 */
3264void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003265 uint8_t uTagRequirement,
3266 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003267{
3268 if(pMe->uLastError != QCBOR_SUCCESS) {
3269 // Already in error state; do nothing.
3270 return;
3271 }
3272
3273 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003274 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003275 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3276 if(pMe->uLastError != QCBOR_SUCCESS) {
3277 return;
3278 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003279
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003280 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003281 &Item,
3282 uTagRequirement,
3283 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003284}
3285
3286
Laurence Lundblade02625d42020-06-25 14:41:41 -07003287/*
3288 Public function, see header qcbor/qcbor_decode.h file
3289 */
3290void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003291 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003292 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003293 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003294{
3295 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003296 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003297
Laurence Lundblade93d89472020-10-03 22:30:50 -07003298 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3299 &Item,
3300 uTagRequirement,
3301 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003302}
3303
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003304
Laurence Lundblade02625d42020-06-25 14:41:41 -07003305/*
3306 Public function, see header qcbor/qcbor_decode.h file
3307 */
3308void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003309 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003310 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003311 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003312{
3313 QCBORItem Item;
3314 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3315
Laurence Lundblade93d89472020-10-03 22:30:50 -07003316 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3317 &Item,
3318 uTagRequirement,
3319 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003320}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003321
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003322
Laurence Lundblade02625d42020-06-25 14:41:41 -07003323/*
3324 Public function, see header qcbor/qcbor_decode.h file
3325 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003326void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003327{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003328 if(pMe->uLastError != QCBOR_SUCCESS) {
3329 // Already in error state; do nothing.
3330 return;
3331 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003332
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003333 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003334 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003335 return;
3336 }
3337
3338 /*
3339 Reset the length of the UsefulInputBuf to what it was before
3340 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003341 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003342 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003343 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003344
3345
Laurence Lundblade02625d42020-06-25 14:41:41 -07003346 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003347 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003348}
3349
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003350
Laurence Lundbladee6430642020-03-14 21:15:44 -07003351
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003352
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003353
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003354
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003355
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003356
Laurence Lundblade93d89472020-10-03 22:30:50 -07003357static QCBORError
3358InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003359{
3360 switch(pItem->uDataType) {
3361 case QCBOR_TYPE_TRUE:
3362 *pBool = true;
3363 return QCBOR_SUCCESS;
3364 break;
3365
3366 case QCBOR_TYPE_FALSE:
3367 *pBool = false;
3368 return QCBOR_SUCCESS;
3369 break;
3370
3371 default:
3372 return QCBOR_ERR_UNEXPECTED_TYPE;
3373 break;
3374 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003375 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003376}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003377
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003378
Laurence Lundblade9b334962020-08-27 10:55:53 -07003379
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003380/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003381 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003382*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003383void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003384{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003385 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003386 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003387 return;
3388 }
3389
Laurence Lundbladec4537442020-04-14 18:53:22 -07003390 QCBORError nError;
3391 QCBORItem Item;
3392
3393 nError = QCBORDecode_GetNext(pMe, &Item);
3394 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003395 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003396 return;
3397 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003398 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003399}
3400
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003401
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003402/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003403 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003404*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003405void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003406{
3407 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003408 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003409
Laurence Lundblade9b334962020-08-27 10:55:53 -07003410 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003411}
3412
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003413
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003414/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003415 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003416*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003417void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3418{
3419 QCBORItem Item;
3420 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3421
Laurence Lundblade9b334962020-08-27 10:55:53 -07003422 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003423}
3424
3425
3426
Laurence Lundbladec7114722020-08-13 05:11:40 -07003427
3428static void ProcessEpochDate(QCBORDecodeContext *pMe,
3429 QCBORItem *pItem,
3430 uint8_t uTagRequirement,
3431 int64_t *pnTime)
3432{
3433 if(pMe->uLastError != QCBOR_SUCCESS) {
3434 // Already in error state, do nothing
3435 return;
3436 }
3437
3438 QCBORError uErr;
3439
3440 const TagSpecification TagSpec =
3441 {
3442 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003443 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3444 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003445 };
3446
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003447 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003448 if(uErr != QCBOR_SUCCESS) {
3449 goto Done;
3450 }
3451
3452 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3453 uErr = DecodeDateEpoch(pItem);
3454 if(uErr != QCBOR_SUCCESS) {
3455 goto Done;
3456 }
3457 }
3458
Laurence Lundblade9b334962020-08-27 10:55:53 -07003459 // Save the tags in the last item's tags in the decode context
3460 // for QCBORDecode_GetNthTagOfLast()
3461 CopyTags(pMe, pItem);
3462
Laurence Lundbladec7114722020-08-13 05:11:40 -07003463 *pnTime = pItem->val.epochDate.nSeconds;
3464
3465Done:
3466 pMe->uLastError = (uint8_t)uErr;
3467}
3468
3469
3470void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
3471 uint8_t uTagRequirement,
3472 int64_t *pnTime)
3473{
3474 if(pMe->uLastError != QCBOR_SUCCESS) {
3475 // Already in error state, do nothing
3476 return;
3477 }
3478
3479 QCBORItem Item;
3480 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3481
3482 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3483}
3484
3485
3486void
3487QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3488 int64_t nLabel,
3489 uint8_t uTagRequirement,
3490 int64_t *pnTime)
3491{
3492 QCBORItem Item;
3493 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3494 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3495}
3496
3497
3498void
3499QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3500 const char *szLabel,
3501 uint8_t uTagRequirement,
3502 int64_t *pnTime)
3503{
3504 QCBORItem Item;
3505 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3506 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3507}
3508
3509
3510
3511
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003512void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3513 TagSpecification TagSpec,
3514 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003515{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003516 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003517 // Already in error state, do nothing
3518 return;
3519 }
3520
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003521 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003522 QCBORItem Item;
3523
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003524 uError = QCBORDecode_GetNext(pMe, &Item);
3525 if(uError != QCBOR_SUCCESS) {
3526 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003527 return;
3528 }
3529
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003530 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003531
3532 if(pMe->uLastError == QCBOR_SUCCESS) {
3533 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003534 } else {
3535 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003536 }
3537}
3538
Laurence Lundbladec4537442020-04-14 18:53:22 -07003539
3540
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003541
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003542static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003543 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003544 UsefulBufC *pValue,
3545 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003546{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003547 const TagSpecification TagSpec =
3548 {
3549 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003550 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3551 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003552 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003553
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003554 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003555 if(uErr != QCBOR_SUCCESS) {
3556 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003557 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003558
3559 *pValue = pItem->val.string;
3560
3561 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3562 *pbIsNegative = false;
3563 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3564 *pbIsNegative = true;
3565 }
3566
3567 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003568}
3569
3570
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003571/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003572 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003573 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003574void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3575 uint8_t uTagRequirement,
3576 UsefulBufC *pValue,
3577 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003578{
3579 if(pMe->uLastError != QCBOR_SUCCESS) {
3580 // Already in error state, do nothing
3581 return;
3582 }
3583
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003584 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003585 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3586 if(uError != QCBOR_SUCCESS) {
3587 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003588 return;
3589 }
3590
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003591 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003592}
3593
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003594
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003595/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003596 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003597*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003598void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3599 int64_t nLabel,
3600 uint8_t uTagRequirement,
3601 UsefulBufC *pValue,
3602 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003603{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003604 QCBORItem Item;
3605 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003606 if(pMe->uLastError != QCBOR_SUCCESS) {
3607 return;
3608 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003609
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003610 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003611}
3612
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003613
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003614/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003615 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003616*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003617void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3618 const char *szLabel,
3619 uint8_t uTagRequirement,
3620 UsefulBufC *pValue,
3621 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003622{
3623 QCBORItem Item;
3624 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003625 if(pMe->uLastError != QCBOR_SUCCESS) {
3626 return;
3627 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003628
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003629 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003630}
3631
3632
3633
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003634
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003635// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003636QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3637 const QCBORItem *pItem,
3638 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003639 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003640{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003641 const TagSpecification TagSpecText =
3642 {
3643 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003644 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3645 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003646 };
3647 const TagSpecification TagSpecBinary =
3648 {
3649 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003650 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3651 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003652 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003653
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003654 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003655
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003656 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003657 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003658 if(pbIsTag257 != NULL) {
3659 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003660 }
3661 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003662 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003663 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003664 if(pbIsTag257 != NULL) {
3665 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003666 }
3667 uReturn = QCBOR_SUCCESS;
3668
3669 } else {
3670 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3671 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003672
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003673 return uReturn;
3674}
3675
Laurence Lundblade93d89472020-10-03 22:30:50 -07003676// Improvement: add methods for wrapped CBOR, a simple alternate
3677// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003678
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003679
3680
3681
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003682#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003683
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003684typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003685
3686
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003687// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003688static QCBORError
3689Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003690{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003691 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003692
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003693 if(uResult != 0) {
3694 /* This loop will run a maximum of 19 times because
3695 * UINT64_MAX < 10 ^^ 19. More than that will cause
3696 * exit with the overflow error
3697 */
3698 for(; nExponent > 0; nExponent--) {
3699 if(uResult > UINT64_MAX / 10) {
3700 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3701 }
3702 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003703 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003704
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003705 for(; nExponent < 0; nExponent++) {
3706 uResult = uResult / 10;
3707 if(uResult == 0) {
3708 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3709 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003710 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003711 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003712 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003713
3714 *puResult = uResult;
3715
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003716 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003717}
3718
3719
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003720// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003721static QCBORError
3722Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003723{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003724 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003725
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003726 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003727
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003728 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003729 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003730 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003731 */
3732 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003733 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003734 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003735 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003736 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003737 nExponent--;
3738 }
3739
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003740 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003741 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003742 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3743 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003744 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003745 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003746 }
3747
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003748 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003749
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003750 return QCBOR_SUCCESS;
3751}
3752
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003753
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003754/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003755 Compute value with signed mantissa and signed result. Works with
3756 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003757 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003758static inline QCBORError ExponentiateNN(int64_t nMantissa,
3759 int64_t nExponent,
3760 int64_t *pnResult,
3761 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003762{
3763 uint64_t uResult;
3764
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003765 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003766 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003767 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3768
3769 // Do the exponentiation of the positive mantissa
3770 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3771 if(uReturn) {
3772 return uReturn;
3773 }
3774
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003775
Laurence Lundblade983500d2020-05-14 11:49:34 -07003776 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3777 of INT64_MIN. This assumes two's compliment representation where
3778 INT64_MIN is one increment farther from 0 than INT64_MAX.
3779 Trying to write -INT64_MIN doesn't work to get this because the
3780 compiler tries to work with an int64_t which can't represent
3781 -INT64_MIN.
3782 */
3783 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3784
3785 // Error out if too large
3786 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003787 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3788 }
3789
3790 // Casts are safe because of checks above
3791 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3792
3793 return QCBOR_SUCCESS;
3794}
3795
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003796
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003797/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003798 Compute value with signed mantissa and unsigned result. Works with
3799 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003800 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003801static inline QCBORError ExponentitateNU(int64_t nMantissa,
3802 int64_t nExponent,
3803 uint64_t *puResult,
3804 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003805{
3806 if(nMantissa < 0) {
3807 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3808 }
3809
3810 // Cast to unsigned is OK because of check for negative
3811 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3812 // Exponentiation is straight forward
3813 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3814}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003815
3816
3817/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003818 Compute value with signed mantissa and unsigned result. Works with
3819 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003820 */
3821static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3822 int64_t nExponent,
3823 uint64_t *puResult,
3824 fExponentiator pfExp)
3825{
3826 return (*pfExp)(uMantissa, nExponent, puResult);
3827}
3828
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003829#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3830
3831
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003832
3833
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003834
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003835static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003836{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003837 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003838
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003839 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003840 const uint8_t *pByte = BigNum.ptr;
3841 size_t uLen = BigNum.len;
3842 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003843 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003844 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003845 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003846 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003847 }
3848
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003849 *pResult = uResult;
3850 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003851}
3852
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003853
Laurence Lundblade887add82020-05-17 05:50:34 -07003854static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003855{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003856 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003857}
3858
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003859
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003860static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003861{
3862 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003863 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3864 if(uError) {
3865 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003866 }
3867 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3868 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003869 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003870}
3871
3872
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003873static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003874{
3875 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003876 /* The negative integer furthest from zero for a C int64_t is
3877 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3878 negative number in CBOR is computed as -n - 1 where n is the
3879 encoded integer, where n is what is in the variable BigNum. When
3880 converting BigNum to a uint64_t, the maximum value is thus
3881 INT64_MAX, so that when it -n - 1 is applied to it the result will
3882 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003883
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003884 -n - 1 <= INT64_MIN.
3885 -n - 1 <= -INT64_MAX - 1
3886 n <= INT64_MAX.
3887 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003888 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003889 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003890 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003891 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003892
3893 /// Now apply -n - 1. The cast is safe because
3894 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3895 // is the largest positive integer that an int64_t can
3896 // represent. */
3897 *pnResult = -(int64_t)uResult - 1;
3898
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003899 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003900}
3901
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003902
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003903
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003904
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003905
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003906/*
3907Convert a integers and floats to an int64_t.
3908
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003909\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003910
Laurence Lundblade93d89472020-10-03 22:30:50 -07003911\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
3912 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003913
3914\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3915
Laurence Lundblade93d89472020-10-03 22:30:50 -07003916\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
3917 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003918*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07003919static QCBORError
3920ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003921{
3922 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003923 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003924 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003925#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003926 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003927 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3928 http://www.cplusplus.com/reference/cmath/llround/
3929 */
3930 // Not interested in FE_INEXACT
3931 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003932 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3933 *pnValue = llround(pItem->val.dfnum);
3934 } else {
3935 *pnValue = lroundf(pItem->val.fnum);
3936 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003937 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
3938 // llround() shouldn't result in divide by zero, but catch
3939 // it here in case it unexpectedly does. Don't try to
3940 // distinguish between the various exceptions because it seems
3941 // they vary by CPU, compiler and OS.
3942 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003943 }
3944 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003945 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003946 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003947#else
3948 return QCBOR_ERR_HW_FLOAT_DISABLED;
3949#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003950 break;
3951
3952 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003953 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003954 *pnValue = pItem->val.int64;
3955 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003956 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003957 }
3958 break;
3959
3960 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003961 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003962 if(pItem->val.uint64 < INT64_MAX) {
3963 *pnValue = pItem->val.int64;
3964 } else {
3965 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3966 }
3967 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003968 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003969 }
3970 break;
3971
3972 default:
3973 return QCBOR_ERR_UNEXPECTED_TYPE;
3974 }
3975 return QCBOR_SUCCESS;
3976}
3977
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003978
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003979void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003980 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003981 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003982 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003983{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003984 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003985 return;
3986 }
3987
Laurence Lundbladee6430642020-03-14 21:15:44 -07003988 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003989 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3990 if(uError) {
3991 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003992 return;
3993 }
3994
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003995 if(pItem) {
3996 *pItem = Item;
3997 }
3998
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003999 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004000}
4001
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004002
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004003void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4004 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004005 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004006 int64_t *pnValue,
4007 QCBORItem *pItem)
4008{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004009 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004010 if(pMe->uLastError != QCBOR_SUCCESS) {
4011 return;
4012 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004013
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004014 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004015}
4016
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004017
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004018void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4019 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004020 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004021 int64_t *pnValue,
4022 QCBORItem *pItem)
4023{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004024 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004025 if(pMe->uLastError != QCBOR_SUCCESS) {
4026 return;
4027 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004028
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004029 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004030}
4031
4032
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004033/*
4034 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004035
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004036 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004037
Laurence Lundblade93d89472020-10-03 22:30:50 -07004038 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4039 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004040
4041 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4042
Laurence Lundblade93d89472020-10-03 22:30:50 -07004043 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4044 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004045 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004046static QCBORError
4047Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004048{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004049 switch(pItem->uDataType) {
4050
4051 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004052 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004053 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004054 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004055 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004056 }
4057 break;
4058
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004059 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004060 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004061 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004062 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004063 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004064 }
4065 break;
4066
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004067#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4068 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004069 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004070 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004071 pItem->val.expAndMantissa.nExponent,
4072 pnValue,
4073 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004074 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004075 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004076 }
4077 break;
4078
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004079 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004080 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004081 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004082 pItem->val.expAndMantissa.nExponent,
4083 pnValue,
4084 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004085 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004086 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004087 }
4088 break;
4089
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004090 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004091 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004092 int64_t nMantissa;
4093 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004094 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4095 if(uErr) {
4096 return uErr;
4097 }
4098 return ExponentiateNN(nMantissa,
4099 pItem->val.expAndMantissa.nExponent,
4100 pnValue,
4101 Exponentitate10);
4102 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004103 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004104 }
4105 break;
4106
4107 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004108 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004109 int64_t nMantissa;
4110 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004111 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4112 if(uErr) {
4113 return uErr;
4114 }
4115 return ExponentiateNN(nMantissa,
4116 pItem->val.expAndMantissa.nExponent,
4117 pnValue,
4118 Exponentitate10);
4119 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004120 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004121 }
4122 break;
4123
4124 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004125 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004126 int64_t nMantissa;
4127 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004128 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4129 if(uErr) {
4130 return uErr;
4131 }
4132 return ExponentiateNN(nMantissa,
4133 pItem->val.expAndMantissa.nExponent,
4134 pnValue,
4135 Exponentitate2);
4136 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004137 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004138 }
4139 break;
4140
4141 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004142 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004143 int64_t nMantissa;
4144 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004145 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4146 if(uErr) {
4147 return uErr;
4148 }
4149 return ExponentiateNN(nMantissa,
4150 pItem->val.expAndMantissa.nExponent,
4151 pnValue,
4152 Exponentitate2);
4153 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004154 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004155 }
4156 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004157#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4158
Laurence Lundbladee6430642020-03-14 21:15:44 -07004159
Laurence Lundbladec4537442020-04-14 18:53:22 -07004160 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004161 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004162}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004163
4164
Laurence Lundbladec4537442020-04-14 18:53:22 -07004165/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004166 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004167 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004168void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004169{
4170 QCBORItem Item;
4171
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004172 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004173
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004174 if(pMe->uLastError == QCBOR_SUCCESS) {
4175 // The above conversion succeeded
4176 return;
4177 }
4178
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004179 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004180 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004181 return;
4182 }
4183
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004184 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004185}
4186
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004187
4188/*
4189Public function, see header qcbor/qcbor_decode.h file
4190*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004191void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4192 int64_t nLabel,
4193 uint32_t uConvertTypes,
4194 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004195{
4196 QCBORItem Item;
4197
Laurence Lundblade93d89472020-10-03 22:30:50 -07004198 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4199 nLabel,
4200 uConvertTypes,
4201 pnValue,
4202 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004203
4204 if(pMe->uLastError == QCBOR_SUCCESS) {
4205 // The above conversion succeeded
4206 return;
4207 }
4208
4209 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4210 // The above conversion failed in a way that code below can't correct
4211 return;
4212 }
4213
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004214 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004215}
4216
4217
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004218/*
4219Public function, see header qcbor/qcbor_decode.h file
4220*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004221void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4222 const char *szLabel,
4223 uint32_t uConvertTypes,
4224 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004225{
4226 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004227 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4228 szLabel,
4229 uConvertTypes,
4230 pnValue,
4231 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004232
4233 if(pMe->uLastError == QCBOR_SUCCESS) {
4234 // The above conversion succeeded
4235 return;
4236 }
4237
4238 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4239 // The above conversion failed in a way that code below can't correct
4240 return;
4241 }
4242
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004243 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004244}
4245
4246
Laurence Lundblade93d89472020-10-03 22:30:50 -07004247static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004248{
4249 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004250 case QCBOR_TYPE_DOUBLE:
4251 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004252#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004253 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004254 // Can't use llround here because it will not convert values
4255 // greater than INT64_MAX and less than UINT64_MAX that
4256 // need to be converted so it is more complicated.
4257 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4258 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4259 if(isnan(pItem->val.dfnum)) {
4260 return QCBOR_ERR_FLOAT_EXCEPTION;
4261 } else if(pItem->val.dfnum < 0) {
4262 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4263 } else {
4264 double dRounded = round(pItem->val.dfnum);
4265 // See discussion in DecodeDateEpoch() for
4266 // explanation of - 0x7ff
4267 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4268 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4269 }
4270 *puValue = (uint64_t)dRounded;
4271 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004272 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004273 if(isnan(pItem->val.fnum)) {
4274 return QCBOR_ERR_FLOAT_EXCEPTION;
4275 } else if(pItem->val.fnum < 0) {
4276 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4277 } else {
4278 float fRounded = roundf(pItem->val.fnum);
4279 // See discussion in DecodeDateEpoch() for
4280 // explanation of - 0x7ff
4281 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4282 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4283 }
4284 *puValue = (uint64_t)fRounded;
4285 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004286 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004287 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4288 // round() and roundf() shouldn't result in exceptions here, but
4289 // catch them to be robust and thorough. Don't try to
4290 // distinguish between the various exceptions because it seems
4291 // they vary by CPU, compiler and OS.
4292 return QCBOR_ERR_FLOAT_EXCEPTION;
4293 }
4294
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004295 } else {
4296 return QCBOR_ERR_UNEXPECTED_TYPE;
4297 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004298#else
4299 return QCBOR_ERR_HW_FLOAT_DISABLED;
4300#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004301 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004302
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004303 case QCBOR_TYPE_INT64:
4304 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4305 if(pItem->val.int64 >= 0) {
4306 *puValue = (uint64_t)pItem->val.int64;
4307 } else {
4308 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4309 }
4310 } else {
4311 return QCBOR_ERR_UNEXPECTED_TYPE;
4312 }
4313 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004314
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004315 case QCBOR_TYPE_UINT64:
4316 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4317 *puValue = pItem->val.uint64;
4318 } else {
4319 return QCBOR_ERR_UNEXPECTED_TYPE;
4320 }
4321 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004322
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004323 default:
4324 return QCBOR_ERR_UNEXPECTED_TYPE;
4325 }
4326
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004327 return QCBOR_SUCCESS;
4328}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004329
4330
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004331void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004332 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004333 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004334 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004335{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004336 if(pMe->uLastError != QCBOR_SUCCESS) {
4337 return;
4338 }
4339
Laurence Lundbladec4537442020-04-14 18:53:22 -07004340 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004341
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004342 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4343 if(uError) {
4344 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004345 return;
4346 }
4347
Laurence Lundbladea826c502020-05-10 21:07:00 -07004348 if(pItem) {
4349 *pItem = Item;
4350 }
4351
Laurence Lundblade93d89472020-10-03 22:30:50 -07004352 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004353}
4354
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004355
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004356void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004357 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004358 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004359 uint64_t *puValue,
4360 QCBORItem *pItem)
4361{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004362 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004363 if(pMe->uLastError != QCBOR_SUCCESS) {
4364 return;
4365 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004366
Laurence Lundblade93d89472020-10-03 22:30:50 -07004367 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004368}
4369
4370
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004371void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004372 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004373 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004374 uint64_t *puValue,
4375 QCBORItem *pItem)
4376{
4377 if(pMe->uLastError != QCBOR_SUCCESS) {
4378 return;
4379 }
4380
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004381 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004382 if(pMe->uLastError != QCBOR_SUCCESS) {
4383 return;
4384 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004385
Laurence Lundblade93d89472020-10-03 22:30:50 -07004386 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004387}
4388
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004389
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004390/*
4391 Public function, see header qcbor/qcbor_decode.h file
4392*/
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
4496*/
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 Lundblade9b334962020-08-27 10:55:53 -07004576static QCBORError ConvertDouble(const QCBORItem *pItem,
4577 uint32_t uConvertTypes,
4578 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004579{
4580 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004581 case QCBOR_TYPE_FLOAT:
4582#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4583 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4584 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004585 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004586 *pdValue = (double)pItem->val.fnum;
4587 } else {
4588 return QCBOR_ERR_UNEXPECTED_TYPE;
4589 }
4590 }
4591#else
4592 return QCBOR_ERR_HW_FLOAT_DISABLED;
4593#endif
4594 break;
4595
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004596 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004597 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4598 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004599 *pdValue = pItem->val.dfnum;
4600 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004601 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004602 }
4603 }
4604 break;
4605
4606 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004607#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004608 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004609 // A simple cast seems to do the job with no worry of exceptions.
4610 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004611 *pdValue = (double)pItem->val.int64;
4612
4613 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004614 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004615 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004616#else
4617 return QCBOR_ERR_HW_FLOAT_DISABLED;
4618#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004619 break;
4620
4621 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004622#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004623 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004624 // A simple cast seems to do the job with no worry of exceptions.
4625 // There will be precision loss for some values.
4626 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004627 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004628 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004629 }
4630 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004631#else
4632 return QCBOR_ERR_HW_FLOAT_DISABLED;
4633#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004634
4635 default:
4636 return QCBOR_ERR_UNEXPECTED_TYPE;
4637 }
4638
4639 return QCBOR_SUCCESS;
4640}
4641
4642
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004643void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004644 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004645 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004646 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004647{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004648 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004649 return;
4650 }
4651
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004652 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004653
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004654 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004655 if(uError) {
4656 pMe->uLastError = (uint8_t)uError;
4657 return;
4658 }
4659
4660 if(pItem) {
4661 *pItem = Item;
4662 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004663
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004664 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004665}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004666
Laurence Lundbladec4537442020-04-14 18:53:22 -07004667
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004668void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4669 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004670 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004671 double *pdValue,
4672 QCBORItem *pItem)
4673{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004674 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004675 if(pMe->uLastError != QCBOR_SUCCESS) {
4676 return;
4677 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004678
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004679 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004680}
4681
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004682
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004683void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4684 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004685 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004686 double *pdValue,
4687 QCBORItem *pItem)
4688{
4689 if(pMe->uLastError != QCBOR_SUCCESS) {
4690 return;
4691 }
4692
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004693 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004694 if(pMe->uLastError != QCBOR_SUCCESS) {
4695 return;
4696 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004697
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004698 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004699}
4700
4701
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004702#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004703static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4704{
4705 double dResult;
4706
4707 dResult = 0.0;
4708 const uint8_t *pByte = BigNum.ptr;
4709 size_t uLen = BigNum.len;
4710 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004711 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004712 while(uLen--) {
4713 dResult = (dResult * 256.0) + (double)*pByte++;
4714 }
4715
4716 return dResult;
4717}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004718#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4719
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004720
Laurence Lundblade93d89472020-10-03 22:30:50 -07004721static QCBORError
4722DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004723{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004724#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004725 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004726 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4727
4728 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004729 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004730
4731#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004732 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004733 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004734 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004735 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4736 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4737 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004738 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004739 }
4740 break;
4741
4742 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004743 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004744 // Underflow gives 0, overflow gives infinity
4745 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4746 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004747 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004748 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004749 }
4750 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004751#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004752
4753 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004754 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004755 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4756 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004757 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004758 }
4759 break;
4760
4761 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004762 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004763 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004764 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004765 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004766 }
4767 break;
4768
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004769#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004770 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004771 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004772 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4773 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4774 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004775 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004776 }
4777 break;
4778
4779 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004780 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004781 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4782 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4783 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004784 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004785 }
4786 break;
4787
4788 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004789 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004790 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4791 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4792 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004793 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004794 }
4795 break;
4796
4797 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004798 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004799 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004800 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4801 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004802 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004803 }
4804 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004805#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4806
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004807 default:
4808 return QCBOR_ERR_UNEXPECTED_TYPE;
4809 }
4810
4811 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004812
4813#else
4814 (void)pItem;
4815 (void)uConvertTypes;
4816 (void)pdValue;
4817 return QCBOR_ERR_HW_FLOAT_DISABLED;
4818#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4819
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004820}
4821
4822
4823/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004824 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004825*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004826void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4827 uint32_t uConvertTypes,
4828 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004829{
4830
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004831 QCBORItem Item;
4832
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004833 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004834
4835 if(pMe->uLastError == QCBOR_SUCCESS) {
4836 // The above conversion succeeded
4837 return;
4838 }
4839
4840 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4841 // The above conversion failed in a way that code below can't correct
4842 return;
4843 }
4844
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004845 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004846}
4847
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004848
4849/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004850 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004851*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004852void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4853 int64_t nLabel,
4854 uint32_t uConvertTypes,
4855 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004856{
4857 QCBORItem Item;
4858
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004859 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004860
4861 if(pMe->uLastError == QCBOR_SUCCESS) {
4862 // The above conversion succeeded
4863 return;
4864 }
4865
4866 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4867 // The above conversion failed in a way that code below can't correct
4868 return;
4869 }
4870
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004871 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004872}
4873
4874
4875/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004876 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004877*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004878void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4879 const char *szLabel,
4880 uint32_t uConvertTypes,
4881 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004882{
4883 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004884 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004885
4886 if(pMe->uLastError == QCBOR_SUCCESS) {
4887 // The above conversion succeeded
4888 return;
4889 }
4890
4891 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4892 // The above conversion failed in a way that code below can't correct
4893 return;
4894 }
4895
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004896 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004897}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004898
4899
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004900
4901
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004902#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004903static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4904{
4905 while((uInt & 0xff00000000000000UL) == 0) {
4906 uInt = uInt << 8;
4907 };
4908
4909 UsefulOutBuf UOB;
4910
4911 UsefulOutBuf_Init(&UOB, Buffer);
4912
4913 while(uInt) {
4914 const uint64_t xx = uInt & 0xff00000000000000UL;
4915 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4916 uInt = uInt << 8;
4917 (void)xx;
4918 }
4919
4920 return UsefulOutBuf_OutUBuf(&UOB);
4921}
4922
4923
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004924static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4925 TagSpecification TagSpec,
4926 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004927{
4928 QCBORError uErr;
4929 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004930 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004931 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004932 if(uErr != QCBOR_SUCCESS) {
4933 goto Done;
4934 }
4935
4936 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4937 break; // Successful exit. Moving on to finish decoding.
4938 }
4939
4940 // The item is an array, which means an undecoded
4941 // mantissa and exponent, so decode it. It will then
4942 // have a different type and exit the loop if.
4943 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4944 if(uErr != QCBOR_SUCCESS) {
4945 goto Done;
4946 }
4947
4948 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07004949 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004950 }
4951Done:
4952 return uErr;
4953}
4954
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004955
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004956static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004957 TagSpecification TagSpec,
4958 QCBORItem *pItem,
4959 int64_t *pnMantissa,
4960 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004961{
4962 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004963
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004964 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004965 if(uErr != QCBOR_SUCCESS) {
4966 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004967 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004968
Laurence Lundblade9b334962020-08-27 10:55:53 -07004969 switch (pItem->uDataType) {
4970
4971 case QCBOR_TYPE_DECIMAL_FRACTION:
4972 case QCBOR_TYPE_BIGFLOAT:
4973 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4974 *pnExponent = pItem->val.expAndMantissa.nExponent;
4975 break;
4976
4977 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4978 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4979 *pnExponent = pItem->val.expAndMantissa.nExponent;
4980 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4981 break;
4982
4983 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4984 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4985 *pnExponent = pItem->val.expAndMantissa.nExponent;
4986 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4987 break;
4988
4989 default:
4990 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
4991 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004992
4993 Done:
4994 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004995}
4996
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004997
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004998static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004999 TagSpecification TagSpec,
5000 QCBORItem *pItem,
5001 UsefulBuf BufferForMantissa,
5002 UsefulBufC *pMantissa,
5003 bool *pbIsNegative,
5004 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005005{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005006 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005007
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005008 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005009 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005010 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005011 }
5012
5013 uint64_t uMantissa;
5014
5015 switch (pItem->uDataType) {
5016
5017 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005018 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005019 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5020 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5021 *pbIsNegative = false;
5022 } else {
5023 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5024 *pbIsNegative = true;
5025 }
5026 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5027 *pnExponent = pItem->val.expAndMantissa.nExponent;
5028 break;
5029
5030 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005031 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005032 *pnExponent = pItem->val.expAndMantissa.nExponent;
5033 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5034 *pbIsNegative = false;
5035 break;
5036
5037 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005038 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005039 *pnExponent = pItem->val.expAndMantissa.nExponent;
5040 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5041 *pbIsNegative = true;
5042 break;
5043
5044 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005045 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005046 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005047
5048Done:
5049 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005050}
5051
5052
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005053/*
5054 Public function, see header qcbor/qcbor_decode.h file
5055*/
5056void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5057 uint8_t uTagRequirement,
5058 int64_t *pnMantissa,
5059 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005060{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005061 if(pMe->uLastError != QCBOR_SUCCESS) {
5062 return;
5063 }
5064
5065 QCBORItem Item;
5066 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5067 if(uError) {
5068 pMe->uLastError = (uint8_t)uError;
5069 return;
5070 }
5071
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005072 const TagSpecification TagSpec =
5073 {
5074 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005075 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5076 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5077 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005078 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005079
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005080 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005081}
5082
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005083
5084/*
5085 Public function, see header qcbor/qcbor_decode.h file
5086*/
5087void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005088 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005089 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005090 int64_t *pnMantissa,
5091 int64_t *pnExponent)
5092{
5093 if(pMe->uLastError != QCBOR_SUCCESS) {
5094 return;
5095 }
5096
5097 QCBORItem Item;
5098 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5099
5100 const TagSpecification TagSpec =
5101 {
5102 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005103 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5104 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5105 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005106 };
5107
5108 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5109}
5110
5111
5112/*
5113 Public function, see header qcbor/qcbor_decode.h file
5114*/
5115void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005116 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005117 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005118 int64_t *pnMantissa,
5119 int64_t *pnExponent)
5120{
5121 if(pMe->uLastError != QCBOR_SUCCESS) {
5122 return;
5123 }
5124
5125 QCBORItem Item;
5126 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5127
5128 const TagSpecification TagSpec =
5129 {
5130 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005131 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5132 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5133 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005134 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005135
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005136 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5137}
5138
5139
5140/*
5141 Public function, see header qcbor/qcbor_decode.h file
5142*/
5143void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5144 uint8_t uTagRequirement,
5145 UsefulBuf MantissaBuffer,
5146 UsefulBufC *pMantissa,
5147 bool *pbMantissaIsNegative,
5148 int64_t *pnExponent)
5149{
5150 if(pMe->uLastError != QCBOR_SUCCESS) {
5151 return;
5152 }
5153
5154 QCBORItem Item;
5155 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5156 if(uError) {
5157 pMe->uLastError = (uint8_t)uError;
5158 return;
5159 }
5160
5161 const TagSpecification TagSpec =
5162 {
5163 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005164 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5165 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5166 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005167 };
5168
Laurence Lundblade93d89472020-10-03 22:30:50 -07005169 ProcessMantissaAndExponentBig(pMe,
5170 TagSpec,
5171 &Item,
5172 MantissaBuffer,
5173 pMantissa,
5174 pbMantissaIsNegative,
5175 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005176}
5177
5178
5179/*
5180 Public function, see header qcbor/qcbor_decode.h file
5181*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005182void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005183 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005184 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005185 UsefulBuf BufferForMantissa,
5186 UsefulBufC *pMantissa,
5187 bool *pbIsNegative,
5188 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005189{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005190 if(pMe->uLastError != QCBOR_SUCCESS) {
5191 return;
5192 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005193
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005194 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005195 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005196 if(pMe->uLastError != QCBOR_SUCCESS) {
5197 return;
5198 }
5199
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005200 const TagSpecification TagSpec =
5201 {
5202 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005203 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5204 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5205 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005206 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005207
Laurence Lundblade93d89472020-10-03 22:30:50 -07005208 ProcessMantissaAndExponentBig(pMe,
5209 TagSpec,
5210 &Item,
5211 BufferForMantissa,
5212 pMantissa,
5213 pbIsNegative,
5214 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005215}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005216
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005217
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005218/*
5219 Public function, see header qcbor/qcbor_decode.h file
5220*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005221void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005222 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005223 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005224 UsefulBuf BufferForMantissa,
5225 UsefulBufC *pMantissa,
5226 bool *pbIsNegative,
5227 int64_t *pnExponent)
5228{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005229 if(pMe->uLastError != QCBOR_SUCCESS) {
5230 return;
5231 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005232
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005233 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005234 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5235 if(pMe->uLastError != QCBOR_SUCCESS) {
5236 return;
5237 }
5238
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005239 const TagSpecification TagSpec =
5240 {
5241 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005242 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5243 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5244 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005245 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005246
5247 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5248}
5249
5250
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005251/*
5252 Public function, see header qcbor/qcbor_decode.h file
5253*/
5254void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5255 uint8_t uTagRequirement,
5256 int64_t *pnMantissa,
5257 int64_t *pnExponent)
5258{
5259 if(pMe->uLastError != QCBOR_SUCCESS) {
5260 return;
5261 }
5262
5263 QCBORItem Item;
5264 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5265 if(uError) {
5266 pMe->uLastError = (uint8_t)uError;
5267 return;
5268 }
5269 const TagSpecification TagSpec =
5270 {
5271 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005272 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5273 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5274 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005275 };
5276
5277 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5278}
5279
5280
5281/*
5282 Public function, see header qcbor/qcbor_decode.h file
5283*/
5284void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005285 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005286 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005287 int64_t *pnMantissa,
5288 int64_t *pnExponent)
5289{
5290 if(pMe->uLastError != QCBOR_SUCCESS) {
5291 return;
5292 }
5293
5294 QCBORItem Item;
5295 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5296 if(pMe->uLastError != QCBOR_SUCCESS) {
5297 return;
5298 }
5299
5300 const TagSpecification TagSpec =
5301 {
5302 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005303 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5304 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5305 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005306 };
5307
5308 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5309}
5310
5311
5312/*
5313 Public function, see header qcbor/qcbor_decode.h file
5314*/
5315void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005316 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005317 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005318 int64_t *pnMantissa,
5319 int64_t *pnExponent)
5320{
5321 if(pMe->uLastError != QCBOR_SUCCESS) {
5322 return;
5323 }
5324
5325 QCBORItem Item;
5326 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5327 if(pMe->uLastError != QCBOR_SUCCESS) {
5328 return;
5329 }
5330
5331 const TagSpecification TagSpec =
5332 {
5333 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005334 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5335 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5336 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005337 };
5338
5339 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5340}
5341
5342
5343/*
5344 Public function, see header qcbor/qcbor_decode.h file
5345*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005346void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5347 uint8_t uTagRequirement,
5348 UsefulBuf MantissaBuffer,
5349 UsefulBufC *pMantissa,
5350 bool *pbMantissaIsNegative,
5351 int64_t *pnExponent)
5352{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005353 if(pMe->uLastError != QCBOR_SUCCESS) {
5354 return;
5355 }
5356
5357 QCBORItem Item;
5358 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5359 if(uError) {
5360 pMe->uLastError = (uint8_t)uError;
5361 return;
5362 }
5363
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005364 const TagSpecification TagSpec =
5365 {
5366 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005367 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5368 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5369 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005370 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005371
5372 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005373}
5374
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005375
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005376/*
5377 Public function, see header qcbor/qcbor_decode.h file
5378*/
5379void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005380 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005381 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005382 UsefulBuf BufferForMantissa,
5383 UsefulBufC *pMantissa,
5384 bool *pbIsNegative,
5385 int64_t *pnExponent)
5386{
5387 if(pMe->uLastError != QCBOR_SUCCESS) {
5388 return;
5389 }
5390
5391 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005392 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5393 if(pMe->uLastError != QCBOR_SUCCESS) {
5394 return;
5395 }
5396
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005397 const TagSpecification TagSpec =
5398 {
5399 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005400 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5401 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5402 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005403 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005404
Laurence Lundblade93d89472020-10-03 22:30:50 -07005405 ProcessMantissaAndExponentBig(pMe,
5406 TagSpec,
5407 &Item,
5408 BufferForMantissa,
5409 pMantissa,
5410 pbIsNegative,
5411 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005412}
5413
5414
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005415/*
5416 Public function, see header qcbor/qcbor_decode.h file
5417*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005418void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005419 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005420 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005421 UsefulBuf BufferForMantissa,
5422 UsefulBufC *pMantissa,
5423 bool *pbIsNegative,
5424 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005425{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005426 if(pMe->uLastError != QCBOR_SUCCESS) {
5427 return;
5428 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005429
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005430 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005431 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5432 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005433 return;
5434 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005435
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005436 const TagSpecification TagSpec =
5437 {
5438 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005439 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5440 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5441 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005442 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005443
Laurence Lundblade93d89472020-10-03 22:30:50 -07005444 ProcessMantissaAndExponentBig(pMe,
5445 TagSpec,
5446 &Item,
5447 BufferForMantissa,
5448 pMantissa,
5449 pbIsNegative,
5450 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005451}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005452
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005453#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */