blob: a34c1d0519109a5d4c1346a66ec7c05bf0521c4b [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
55// TODO: add more tests for QCBOR_TYPE_MAP_AS_ARRAY mode in qcbor_decode_tests.c
56QCBORItem_IsMapOrArray(const QCBORItem *pMe)
57{
58 const uint8_t uDataType = pMe->uDataType;
59 return uDataType == QCBOR_TYPE_MAP ||
60 uDataType == QCBOR_TYPE_ARRAY ||
61 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
62}
63
64inline static bool
65QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
66{
67 if(!QCBORItem_IsMapOrArray(pMe)){
68 return false;
69 }
70
71 if(pMe->val.uCount != 0) {
72 return false;
73 }
74 return true;
75}
76
77inline static bool
78QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
79{
80 if(!QCBORItem_IsMapOrArray(pMe)){
81 return false;
82 }
83
84 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
85 return false;
86 }
87 return true;
88}
89
90
Laurence Lundbladeee851742020-01-08 08:37:05 -080091/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070092 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080093 ===========================================================================*/
94
Laurence Lundblade9c905e82020-04-25 11:31:38 -070095/*
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070096 See commecnts about and typedef of QCBORDecodeNesting in qcbor_private.h, the data structure
97 all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -070098
Laurence Lundblade9c905e82020-04-25 11:31:38 -070099
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700100
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700101 */
102
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700103
104inline static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700105DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700106{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700107 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700108 /*
109 Limit in DecodeNesting_Descend against more than
110 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
111 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700112 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700113}
114
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700115
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700116inline static uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700117DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700118{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700119 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700120 /*
121 Limit in DecodeNesting_Descend against more than
122 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
123 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700124 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700125}
126
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700127
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700128static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700129DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700130{
131 return pNesting->pCurrentBounded->u.ma.uStartOffset;
132}
133
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700134
Laurence Lundblade085d7952020-07-24 10:26:30 -0700135static inline bool
136DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
137{
138 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
139 return true;
140 } else {
141 return false;
142 }
143}
144
145
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700146inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700147DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700148{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700149 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700150 return true;
151 } else {
152 return false;
153 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700154}
155
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700156
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700157inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700158DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700159{
160 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700161 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700162 return false;
163 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700164 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700165 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700166 return false;
167 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700168 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700169 return true;
170}
171
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700172
Laurence Lundblade642282a2020-06-23 12:00:33 -0700173inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700174DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700175{
176 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700177 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700178 return true;
179 }
180 return false;
181}
182
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700183
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700184inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700185{
186 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
187 return true;
188 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700189 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700190 return true;
191 }
192 return false;
193}
194
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700195
Laurence Lundblade085d7952020-07-24 10:26:30 -0700196inline static void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700197{
198 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700199 /*
200 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
201 larger than DecodeNesting_EnterBoundedMode which keeps it less than
202 uin32_t so the cast is safe.
203 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700204 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700205
206 if(bIsEmpty) {
207 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
208 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700209}
210
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700211
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700212inline static void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700213{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700214 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700215}
216
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700217
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700218inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700219DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700220{
221 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700222 // No bounded map or array or... set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700223 return false;
224 }
225 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700226 // Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700227 return false;
228 }
229 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700230 // Not at a bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700231 return false;
232 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700233 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700234 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700235 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700236 return false;
237 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700238 // All checks passed, got to the end of a map/array
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700239 return true;
240}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700241
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700242
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700243inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700244DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700245{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700246 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700247 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
248 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700249 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700250 return false;
251 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700252}
253
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700254
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700255inline static bool
256DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700257{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700258 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
259 return true;
260 } else {
261 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700262 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700263}
264
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700265
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700266inline static bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700267DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700268{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700269 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700270 return false;
271 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700272
273 if(pNesting->pCurrentBounded->uLevelType != uType) {
274 return false;
275 }
276
277 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700278}
279
Laurence Lundblade02625d42020-06-25 14:41:41 -0700280
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700281inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700282DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700283{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700284 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700285 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700286}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700287
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700288
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700289inline static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700290DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
291{
292 // Only call on a defnite length array / map
293 pNesting->pCurrent->u.ma.uCountCursor++;
294}
295
296
297inline static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700298DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
299{
300 pNesting->pCurrent--;
301}
302
Laurence Lundblade02625d42020-06-25 14:41:41 -0700303
304static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700305DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700306{
307 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700308 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700309 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700310 }
311
312 // The actual descend
313 pNesting->pCurrent++;
314
315 pNesting->pCurrent->uLevelType = uType;
316
317 return QCBOR_SUCCESS;
318}
319
320
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700321inline static QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700322DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700323{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700324 /*
325 Should only be called on map/array.
326
327 Have descended into this before this is called. The job here is
328 just to mark it in bounded mode.
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700329
330 Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
331 uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700332 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700333 if(uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700334 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700335 }
336
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700337 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700338
339 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700340
341 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700342}
343
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700344
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700345inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700346DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700347 uint8_t uQCBORType,
348 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700349{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700350 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700351
352 if(uCount == 0) {
353 // Nothing to do for empty definite lenth arrays. They are just are
354 // effectively the same as an item that is not a map or array
355 goto Done;
356 // Empty indefinite length maps and arrays are handled elsewhere
357 }
358
359 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700360 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
361 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700362 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700363 goto Done;
364 }
365
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700366 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700367 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700368 goto Done;
369 }
370
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700371 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700372 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
373 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700374
375 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700376
377Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700378 return uError;;
379}
380
381
382static inline void
383DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
384{
385 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
386}
387
388
389static inline void
390DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
391{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700392 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700393 pNesting->pCurrentBounded--;
394 if(DecodeNesting_IsCurrentBounded(pNesting)) {
395 break;
396 }
397 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700398}
399
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700400static inline void
401DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
402{
403 pNesting->pCurrent = pNesting->pCurrentBounded;
404}
405
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700406
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700407inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700408DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700409 uint32_t uEndOffset,
410 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700411{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700412 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700413
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700414 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700415 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700416 goto Done;
417 }
418
Laurence Lundblade02625d42020-06-25 14:41:41 -0700419 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700420 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
421 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700422
Laurence Lundblade02625d42020-06-25 14:41:41 -0700423 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700424 pNesting->pCurrentBounded = pNesting->pCurrent;
425
426Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700427 return uError;;
428}
429
Laurence Lundbladed0304932020-06-27 10:59:38 -0700430
431static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700432DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700433{
434 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700435}
436
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700437
Laurence Lundbladeee851742020-01-08 08:37:05 -0800438inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700439DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700440{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700441 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700442 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
443 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700444}
445
446
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700447inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700448DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700449{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700450 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700451 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700452 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700453}
454
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700455
Laurence Lundblade02625d42020-06-25 14:41:41 -0700456static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700457DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700458{
459 *pNesting = *pSave;
460}
461
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700462
Laurence Lundblade02625d42020-06-25 14:41:41 -0700463static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700464DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700465{
466 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
467}
468
469
Laurence Lundblade02625d42020-06-25 14:41:41 -0700470static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700471DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700472{
473 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
474}
475
476
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700477
Laurence Lundbladeee851742020-01-08 08:37:05 -0800478/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800479 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
480
481 The following four functions are pretty wrappers for invocation of
482 the string allocator supplied by the caller.
483
Laurence Lundbladeee851742020-01-08 08:37:05 -0800484 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800485
Laurence Lundbladeee851742020-01-08 08:37:05 -0800486static inline void
487StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800488{
489 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
490}
491
Laurence Lundbladeee851742020-01-08 08:37:05 -0800492// StringAllocator_Reallocate called with pMem NULL is
493// equal to StringAllocator_Allocate()
494static inline UsefulBuf
495StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
496 void *pMem,
497 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800498{
499 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
500}
501
Laurence Lundbladeee851742020-01-08 08:37:05 -0800502static inline UsefulBuf
503StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800504{
505 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
506}
507
Laurence Lundbladeee851742020-01-08 08:37:05 -0800508static inline void
509StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800510{
511 if(pMe->pfAllocator) {
512 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
513 }
514}
515
516
517
Laurence Lundbladeee851742020-01-08 08:37:05 -0800518/*===========================================================================
519 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700520
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800521 See qcbor/qcbor_decode.h for definition of the object
522 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800523 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700524/*
525 Public function, see header file
526 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800527void QCBORDecode_Init(QCBORDecodeContext *me,
528 UsefulBufC EncodedCBOR,
529 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700530{
531 memset(me, 0, sizeof(QCBORDecodeContext));
532 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800533 // Don't bother with error check on decode mode. If a bad value is
534 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700535 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700536 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700537 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700538 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700539 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700540}
541
542
543/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700544 Public function, see header file
545 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800546void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
547 QCBORStringAllocate pfAllocateFunction,
548 void *pAllocateContext,
549 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700550{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800551 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
552 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
553 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700554}
555
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800556
557/*
558 Public function, see header file
559 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700560void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800561 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700562{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700563 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700564 (void)pMe;
565 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700566}
567
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700568
569/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800570 This decodes the fundamental part of a CBOR data item, the type and
571 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800572
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700573 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800574
Laurence Lundbladeee851742020-01-08 08:37:05 -0800575 This does the network->host byte order conversion. The conversion
576 here also results in the conversion for floats in addition to that
577 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800578
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700579 This returns:
580 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800581
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800582 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800583 tags and floats and length for strings and arrays
584
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800585 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800586 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800587
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800588 The int type is preferred to uint8_t for some variables as this
589 avoids integer promotions, can reduce code size and makes
590 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700591
592 @retval QCBOR_ERR_UNSUPPORTED
593
594 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700595 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800596inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
597 int *pnMajorType,
598 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800599 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700600{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700601 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800602
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700603 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800604 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800605
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700606 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800607 const int nTmpMajorType = nInitialByte >> 5;
608 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800609
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800610 // Where the number or argument accumulates
611 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800612
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800613 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700614 // Need to get 1,2,4 or 8 additional argument bytes. Map
615 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800616 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800617
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800618 // Loop getting all the bytes in the argument
619 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800620 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800621 // This shift and add gives the endian conversion
622 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
623 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800624 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800625 // The reserved and thus-far unused additional info values
626 nReturn = QCBOR_ERR_UNSUPPORTED;
627 goto Done;
628 } else {
629 // Less than 24, additional info is argument or 31, an indefinite length
630 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800631 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700632 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800633
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700634 if(UsefulInputBuf_GetError(pUInBuf)) {
635 nReturn = QCBOR_ERR_HIT_END;
636 goto Done;
637 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800638
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639 // All successful if we got here.
640 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800641 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800642 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800643 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800644
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700645Done:
646 return nReturn;
647}
648
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800649
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700650/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800651 CBOR doesn't explicitly specify two's compliment for integers but all
652 CPUs use it these days and the test vectors in the RFC are so. All
653 integers in the CBOR structure are positive and the major type
654 indicates positive or negative. CBOR can express positive integers
655 up to 2^x - 1 where x is the number of bits and negative integers
656 down to 2^x. Note that negative numbers can be one more away from
657 zero than positive. Stdint, as far as I can tell, uses two's
658 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800659
Laurence Lundblade9b334962020-08-27 10:55:53 -0700660 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800661 used carefully here, and in particular why it isn't used in the interface.
662 Also see
663 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
664
665 Int is used for values that need less than 16-bits and would be subject
666 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700667
668 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700669 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800670inline static QCBORError
671DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700672{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700673 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800674
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700675 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
676 if (uNumber <= INT64_MAX) {
677 pDecodedItem->val.int64 = (int64_t)uNumber;
678 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800679
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700680 } else {
681 pDecodedItem->val.uint64 = uNumber;
682 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800683
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700684 }
685 } else {
686 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800687 // CBOR's representation of negative numbers lines up with the
688 // two-compliment representation. A negative integer has one
689 // more in range than a positive integer. INT64_MIN is
690 // equal to (-INT64_MAX) - 1.
691 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700692 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800693
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700694 } else {
695 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000696 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700697 nReturn = QCBOR_ERR_INT_OVERFLOW;
698 }
699 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800700
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701 return nReturn;
702}
703
704// Make sure #define value line up as DecodeSimple counts on this.
705#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
706#error QCBOR_TYPE_FALSE macro value wrong
707#endif
708
709#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
710#error QCBOR_TYPE_TRUE macro value wrong
711#endif
712
713#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
714#error QCBOR_TYPE_NULL macro value wrong
715#endif
716
717#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
718#error QCBOR_TYPE_UNDEF macro value wrong
719#endif
720
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700721#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
722#error QCBOR_TYPE_BREAK macro value wrong
723#endif
724
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700725#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
726#error QCBOR_TYPE_DOUBLE macro value wrong
727#endif
728
729#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
730#error QCBOR_TYPE_FLOAT macro value wrong
731#endif
732
733/*
734 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700735
736 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
737
738 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700739 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800740inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800741DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700743 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800744
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700745 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800746 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700747 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800748 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800749
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800750 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800751 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
752 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800753
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700754 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700755#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700756 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700757 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700758 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700759 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
760 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700761#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700762 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700763#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700764 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700765 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700766 // Single precision is normally returned as a double
767 // since double is widely supported, there is no loss of
768 // precision, it makes it easy for the caller in
769 // most cases and it can be converted back to single
770 // with no loss of precision
771 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700772 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700773 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700774 {
775 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
776#ifndef QCBOR_DISABLE_FLOAT_HW_USE
777 // In the normal case, use HW to convert float to double.
778 pDecodedItem->val.dfnum = (double)f;
779 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700780#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700781 // Use of float HW is disabled, return as a float.
782 pDecodedItem->val.fnum = f;
783 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
784
785 // IEEE754_FloatToDouble() could be used here to return
786 // as a double, but it adds object code and most likely
787 // anyone disabling FLOAT HW use doesn't care about
788 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700789#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700790 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700791 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700792
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700793 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700794 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700795 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700796 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800797
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700798 case CBOR_SIMPLEV_FALSE: // 20
799 case CBOR_SIMPLEV_TRUE: // 21
800 case CBOR_SIMPLEV_NULL: // 22
801 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700802 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700803 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800804
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700805 case CBOR_SIMPLEV_ONEBYTE: // 24
806 if(uNumber <= CBOR_SIMPLE_BREAK) {
807 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700808 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700809 goto Done;
810 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800811 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700812 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800813
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700814 default: // 0-19
815 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800816 /*
817 DecodeTypeAndNumber will make uNumber equal to
818 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
819 safe because the 2, 4 and 8 byte lengths of uNumber are in
820 the double/float cases above
821 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700822 pDecodedItem->val.uSimple = (uint8_t)uNumber;
823 break;
824 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800825
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700826Done:
827 return nReturn;
828}
829
830
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700831/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530832 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700833
834 @retval QCBOR_ERR_HIT_END
835
836 @retval QCBOR_ERR_STRING_ALLOCATE
837
838 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700839 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800840inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
841 int nMajorType,
842 uint64_t uStrLen,
843 UsefulInputBuf *pUInBuf,
844 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700845{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700846 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800847
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800848 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
849 // This check makes the casts to size_t below safe.
850
851 // 4 bytes less than the largest sizeof() so this can be tested by
852 // putting a SIZE_MAX length in the CBOR test input (no one will
853 // care the limit on strings is 4 bytes shorter).
854 if(uStrLen > SIZE_MAX-4) {
855 nReturn = QCBOR_ERR_STRING_TOO_LONG;
856 goto Done;
857 }
858
859 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530860 if(UsefulBuf_IsNULLC(Bytes)) {
861 // Failed to get the bytes for this string item
862 nReturn = QCBOR_ERR_HIT_END;
863 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700864 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530865
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800866 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530867 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800868 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530869 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700870 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530871 goto Done;
872 }
873 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800874 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530875 } else {
876 // Normal case with no string allocator
877 pDecodedItem->val.string = Bytes;
878 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800879 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800880 // Cast because ternary operator causes promotion to integer
881 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
882 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800883
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530884Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700885 return nReturn;
886}
887
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700888
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800889
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700890
891
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700892
893
Laurence Lundbladeee851742020-01-08 08:37:05 -0800894// Make sure the constants align as this is assumed by
895// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700896#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
897#error QCBOR_TYPE_ARRAY value not lined up with major type
898#endif
899#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
900#error QCBOR_TYPE_MAP value not lined up with major type
901#endif
902
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700903/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800904 This gets a single data item and decodes it including preceding
905 optional tagging. This does not deal with arrays and maps and nesting
906 except to decode the data item introducing them. Arrays and maps are
907 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800908
Laurence Lundbladeee851742020-01-08 08:37:05 -0800909 Errors detected here include: an array that is too long to decode,
910 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700911
912 @retval QCBOR_ERR_UNSUPPORTED
913
914 @retval QCBOR_ERR_HIT_END
915
916 @retval QCBOR_ERR_INT_OVERFLOW
917
918 @retval QCBOR_ERR_STRING_ALLOCATE
919
920 @retval QCBOR_ERR_STRING_TOO_LONG
921
922 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
923
924 @retval QCBOR_ERR_BAD_TYPE_7
925
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700926 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800927static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
928 QCBORItem *pDecodedItem,
929 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700930{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700931 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800932
Laurence Lundbladeee851742020-01-08 08:37:05 -0800933 /*
934 Get the major type and the number. Number could be length of more
935 bytes or the value depending on the major type nAdditionalInfo is
936 an encoding of the length of the uNumber and is needed to decode
937 floats and doubles
938 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800939 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700940 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800941 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800942
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700943 memset(pDecodedItem, 0, sizeof(QCBORItem));
944
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800945 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800946
Laurence Lundbladeee851742020-01-08 08:37:05 -0800947 // Error out here if we got into trouble on the type and number. The
948 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700949 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700950 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700951 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800952
Laurence Lundbladeee851742020-01-08 08:37:05 -0800953 // At this point the major type and the value are valid. We've got
954 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800955 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700956 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
957 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800958 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700959 nReturn = QCBOR_ERR_BAD_INT;
960 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800961 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700962 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700963 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800964
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700965 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
966 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800967 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
968 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
969 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
970 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530971 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700972 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800973 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700974 }
975 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800976
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700977 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
978 case CBOR_MAJOR_TYPE_MAP: // Major type 5
979 // Record the number of items in the array or map
980 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700981 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700982 goto Done;
983 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800984 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700985 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700986 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800987 // type conversion OK because of check above
988 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700989 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800990 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800991 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
992 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700993 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800994
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700995 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800996 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700997 nReturn = QCBOR_ERR_BAD_INT;
998 } else {
999 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001000 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001001 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001003
Laurence Lundbladeee851742020-01-08 08:37:05 -08001004 case CBOR_MAJOR_TYPE_SIMPLE:
1005 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001006 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001007 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001008
Laurence Lundbladeee851742020-01-08 08:37:05 -08001009 default:
1010 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001011 nReturn = QCBOR_ERR_UNSUPPORTED;
1012 break;
1013 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001014
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001015Done:
1016 return nReturn;
1017}
1018
1019
1020
1021/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001022 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001023 individual chunk items together into one QCBORItem using the string
1024 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001025
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301026 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade9b334962020-08-27 10:55:53 -07001027
1028 @retval QCBOR_ERR_UNSUPPORTED
1029
1030 @retval QCBOR_ERR_HIT_END
1031
1032 @retval QCBOR_ERR_INT_OVERFLOW
1033
1034 @retval QCBOR_ERR_STRING_ALLOCATE
1035
1036 @retval QCBOR_ERR_STRING_TOO_LONG
1037
1038 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1039
1040 @retval QCBOR_ERR_BAD_TYPE_7
1041
1042 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1043
1044 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001045 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001046static inline QCBORError
1047GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001048{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001049 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001050
1051 // Get pointer to string allocator. First use is to pass it to
1052 // GetNext_Item() when option is set to allocate for *every* string.
1053 // Second use here is to allocate space to coallese indefinite
1054 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001055 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1056 &(me->StringAllocator) :
1057 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001058
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001059 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001060 nReturn = GetNext_Item(&(me->InBuf),
1061 pDecodedItem,
1062 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001063 if(nReturn) {
1064 goto Done;
1065 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001066
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001067 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301068 // code in this function from here down can be eliminated. Run tests, except
1069 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001070
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001071 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001072 const uint8_t uStringType = pDecodedItem->uDataType;
1073 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001074 goto Done; // no need to do any work here on non-string types
1075 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001076
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001077 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301078 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001079 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001080 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001081
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301082 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001083 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001084 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1085 goto Done;
1086 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001087
Laurence Lundblade4b270642020-08-14 12:53:07 -07001088 // Loop getting chunks of the indefinite length string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001089 UsefulBufC FullString = NULLUsefulBufC;
1090
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001091 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001092 // Get item for next chunk
1093 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001094 // NULL string allocator passed here. Do not need to allocate
1095 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001096 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001097 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001098 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001099 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001100
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301101 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001102 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001103 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001104 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301105 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001106 break;
1107 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001108
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001109 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301110 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001111 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001112 if(StringChunkItem.uDataType != uStringType ||
1113 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001114 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001115 break;
1116 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001117
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301118 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001119 // The first time throurgh FullString.ptr is NULL and this is
1120 // equivalent to StringAllocator_Allocate()
1121 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1122 UNCONST_POINTER(FullString.ptr),
1123 FullString.len + StringChunkItem.val.string.len);
1124
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001125 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301126 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001127 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001128 break;
1129 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001130
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001131 // Copy new string chunk at the end of string so far.
1132 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001133 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001134
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001135 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1136 // Getting the item failed, clean up the allocated memory
1137 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001138 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001139
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001140Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001141 return nReturn;
1142}
1143
Laurence Lundblade9b334962020-08-27 10:55:53 -07001144static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001145 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001146 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001147 } else if(uTagVal == CBOR_TAG_INVALID16) {
1148 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001149 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001150 const int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001151 return me->auMappedTags[x];
1152 }
1153}
1154
Laurence Lundblade9b334962020-08-27 10:55:53 -07001155
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001156/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001157 Gets all optional tag data items preceding a data item that is not an
1158 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001159
1160 @retval QCBOR_ERR_UNSUPPORTED
1161
1162 @retval QCBOR_ERR_HIT_END
1163
1164 @retval QCBOR_ERR_INT_OVERFLOW
1165
1166 @retval QCBOR_ERR_STRING_ALLOCATE
1167
1168 @retval QCBOR_ERR_STRING_TOO_LONG
1169
1170 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1171
1172 @retval QCBOR_ERR_BAD_TYPE_7
1173
1174 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1175
1176 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1177
1178 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001179 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001180static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001181GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001182{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001183 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1184 CBOR_TAG_INVALID16,
1185 CBOR_TAG_INVALID16,
1186 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001187
Laurence Lundblade9b334962020-08-27 10:55:53 -07001188 QCBORError uReturn = QCBOR_SUCCESS;
1189
Laurence Lundblade59289e52019-12-30 13:44:37 -08001190 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001191 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001192 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1193 if(uErr != QCBOR_SUCCESS) {
1194 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001195 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001196 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001197
Laurence Lundblade9b334962020-08-27 10:55:53 -07001198 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001199 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001200 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001201 break;
1202 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001203
Laurence Lundblade9b334962020-08-27 10:55:53 -07001204 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1205 // No room in the tag list
1206 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1207 // Continue on to get all tags on this item even though
1208 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001209 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001210 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001211 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001212 // Slide tags over one in the array to make room at index 0
1213 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1214 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001215 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001216
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001217 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001218 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001219 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001220 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001221 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001222 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001223 break;
1224 }
1225 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1226 break;
1227 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001228 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001229 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1230 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001231 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1232 // Continue on to get all tags on this item even though
1233 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001234 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001235 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001236 }
1237
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001238 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001239 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001240 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001241
1242 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001243 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001244 }
1245 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001246
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001247Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001248 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001249}
1250
1251
1252/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001253 This layer takes care of map entries. It combines the label and data
1254 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001255
1256 @retval QCBOR_ERR_UNSUPPORTED
1257
1258 @retval QCBOR_ERR_HIT_END
1259
1260 @retval QCBOR_ERR_INT_OVERFLOW
1261
1262 @retval QCBOR_ERR_STRING_ALLOCATE
1263
1264 @retval QCBOR_ERR_STRING_TOO_LONG
1265
1266 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1267
1268 @retval QCBOR_ERR_BAD_TYPE_7
1269
1270 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1271
1272 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1273
1274 @retval QCBOR_ERR_TOO_MANY_TAGS
1275
1276 @retval QCBOR_ERR_MAP_LABEL_TYPE
1277
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001278 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001279 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001280static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001281GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001282{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001283 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001284 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001285 if(nReturn)
1286 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001287
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001288 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001289 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001290 goto Done;
1291 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001292
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001293 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1294 // In a map and caller wants maps decoded, not treated as arrays
1295
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001296 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001297 // If in a map and the right decoding mode, get the label
1298
Laurence Lundbladeee851742020-01-08 08:37:05 -08001299 // Save label in pDecodedItem and get the next which will
1300 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001301 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001302 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001303 if(nReturn)
1304 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001305
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301306 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001307
1308 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1309 // strings are always good labels
1310 pDecodedItem->label.string = LabelItem.val.string;
1311 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1312 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001313 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001314 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1315 goto Done;
1316 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1317 pDecodedItem->label.int64 = LabelItem.val.int64;
1318 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1319 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1320 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1321 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1322 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1323 pDecodedItem->label.string = LabelItem.val.string;
1324 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1325 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1326 } else {
1327 // label is not an int or a string. It is an arrray
1328 // or a float or such and this implementation doesn't handle that.
1329 // Also, tags on labels are ignored.
1330 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1331 goto Done;
1332 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001333 }
1334 } else {
1335 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001336 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001337 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001338 goto Done;
1339 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001340 // Decoding a map as an array
1341 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001342 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1343 // Cast is needed because of integer promotion
1344 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001345 }
1346 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001347
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001348Done:
1349 return nReturn;
1350}
1351
1352
Laurence Lundblade02625d42020-06-25 14:41:41 -07001353/*
1354 See if next item is a CBOR break. If it is, it is consumed,
1355 if not it is not consumed.
1356*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001357static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001358NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1359{
1360 *pbNextIsBreak = false;
1361 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001362 QCBORItem Peek;
1363 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1364 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1365 if(uReturn != QCBOR_SUCCESS) {
1366 return uReturn;
1367 }
1368 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001369 // It is not a break, rewind so it can be processed normally.
1370 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001371 } else {
1372 *pbNextIsBreak = true;
1373 }
1374 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001375
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001376 return QCBOR_SUCCESS;
1377}
1378
1379
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001380/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001381 An item was just consumed, now figure out if it was the
1382 end of an array or map that can be closed out. That
1383 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001384*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001385static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001386{
1387 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001388
Laurence Lundblade642282a2020-06-23 12:00:33 -07001389 /* This loops ascending nesting levels as long as there is ascending to do */
1390 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1391
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001392 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001393 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001394 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1395 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001396 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001397 break;
1398 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001399 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001400
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001401 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001402 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001403 bool bIsBreak = false;
1404 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1405 if(uReturn != QCBOR_SUCCESS) {
1406 goto Done;
1407 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001408
1409 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001410 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001411 break;
1412 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001413
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001414 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001415 /*
1416 Break occurred inside a bstr-wrapped CBOR or
1417 in the top level sequence. This is always an
1418 error because neither are an indefinte length
1419 map/array.
1420 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001421 uReturn = QCBOR_ERR_BAD_BREAK;
1422 goto Done;
1423 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001424
Laurence Lundblade02625d42020-06-25 14:41:41 -07001425 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001426 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001427
Laurence Lundblade02625d42020-06-25 14:41:41 -07001428 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001429
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001430 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001431 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001432 /* Set the count to zero for definite length arrays to indicate cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001433 if(bMarkEnd) {
1434 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001435 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001436
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001437 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001438 break;
1439 }
1440
1441 /* Finally, actually ascend one level. */
1442 DecodeNesting_Ascend(&(pMe->nesting));
1443 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001444
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001445 uReturn = QCBOR_SUCCESS;
1446
1447Done:
1448 return uReturn;
1449}
1450
1451
1452/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001453 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001454 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1455 indefinte length maps and arrays by looking at the item count or
1456 finding CBOR breaks. It detects the ends of the top-level sequence
1457 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001458
1459 @retval QCBOR_ERR_UNSUPPORTED X
1460
1461 @retval QCBOR_ERR_HIT_END
1462
1463 @retval QCBOR_ERR_INT_OVERFLOW X
1464
1465 @retval QCBOR_ERR_STRING_ALLOCATE
1466
1467 @retval QCBOR_ERR_STRING_TOO_LONG
1468
1469 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1470
1471 @retval QCBOR_ERR_BAD_TYPE_7 X
1472
1473 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1474
1475 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1476
1477 @retval QCBOR_ERR_TOO_MANY_TAGS
1478
1479 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1480
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001481 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001482
1483 @retval QCBOR_ERR_NO_MORE_ITEMS
1484
1485 @retval QCBOR_ERR_BAD_BREAK
1486
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001487 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001488static QCBORError
1489QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001490{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001491 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001492 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001493
Laurence Lundblade642282a2020-06-23 12:00:33 -07001494 /*
1495 If out of bytes to consume, it is either the end of the top-level
1496 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001497
Laurence Lundblade642282a2020-06-23 12:00:33 -07001498 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1499 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1500 CBOR is exited, the length is set back to the top-level's length
1501 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001502 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001503 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001504 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001505 goto Done;
1506 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001507
Laurence Lundblade642282a2020-06-23 12:00:33 -07001508 /*
1509 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001510 array. The check for the end of an indefinite length array is
1511 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001512 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001513 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001514 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001515 goto Done;
1516 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001517
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001518 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001519 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001520 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1521 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001522 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001523 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301524
Laurence Lundblade642282a2020-06-23 12:00:33 -07001525 /*
1526 Breaks ending arrays/maps are always processed at the end of this
1527 function. They should never show up here.
1528 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301529 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001530 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301531 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301532 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001533
Laurence Lundblade642282a2020-06-23 12:00:33 -07001534 /*
1535 Record the nesting level for this data item before processing any
1536 of decrementing and descending.
1537 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001538 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001539
Laurence Lundblade642282a2020-06-23 12:00:33 -07001540
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001541 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001542 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001543 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001544 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001545
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001546 Empty indefinite length maps and arrays are descended into, but then ascended out
Laurence Lundblade02625d42020-06-25 14:41:41 -07001547 of in the next chunk of code.
1548
1549 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001550 encloses them so a decrement needs to be done for them too, but
1551 that is done only when all the items in them have been
1552 processed, not when they are opened with the exception of an
1553 empty map or array.
1554 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001555 QCBORError uDescendErr;
1556 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001557 pDecodedItem->uDataType,
1558 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001559 if(uDescendErr != QCBOR_SUCCESS) {
1560 /* This error is probably a traversal error and it
1561 overrides the non-traversal error. */
1562 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001563 goto Done;
1564 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001565 }
1566
Laurence Lundblade02625d42020-06-25 14:41:41 -07001567 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1568 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1569 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001570 /*
1571 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001572 - A non-aggregate like an integer or string
1573 - An empty definite length map or array
1574 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001575
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001576 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001577 definite length map/array and break detection for an indefinite
1578 length map/array. If the end of the map/array was reached, then
1579 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001580 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001581 QCBORError uAscendErr;
1582 uAscendErr = NestLevelAscender(me, true);
1583 if(uAscendErr != QCBOR_SUCCESS) {
1584 /* This error is probably a traversal error and it
1585 overrides the non-traversal error. */
1586 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001587 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001588 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301589 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001590
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001591 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001592 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001593 Tell the caller what level is next. This tells them what
1594 maps/arrays were closed out and makes it possible for them to
1595 reconstruct the tree with just the information returned in
1596 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001597 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001598 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001599 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001600 pDecodedItem->uNextNestLevel = 0;
1601 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001602 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001603 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001604
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001605Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001606 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001607 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001608 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1609 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1610 // memset(pDecodedItem, 0, sizeof(QCBORItem));
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001611 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001612 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001613}
1614
Laurence Lundblade9b334962020-08-27 10:55:53 -07001615static void ShiftTags(QCBORItem *pDecodedItem)
1616{
1617 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1618 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1619 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1620 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1621}
1622
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001623
Laurence Lundblade59289e52019-12-30 13:44:37 -08001624/*
1625 Mostly just assign the right data type for the date string.
1626 */
1627inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1628{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001629 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1630 return QCBOR_ERR_BAD_OPT_TAG;
1631 }
1632
1633 const UsefulBufC Temp = pDecodedItem->val.string;
1634 pDecodedItem->val.dateString = Temp;
1635 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001636 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001637 return QCBOR_SUCCESS;
1638}
1639
1640
Laurence Lundblade9b334962020-08-27 10:55:53 -07001641
Laurence Lundblade59289e52019-12-30 13:44:37 -08001642/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001643 The epoch formatted date. Turns lots of different forms of encoding
1644 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001645 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001646static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001647{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001648 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001649
1650 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1651
1652 switch (pDecodedItem->uDataType) {
1653
1654 case QCBOR_TYPE_INT64:
1655 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1656 break;
1657
1658 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001659 // This only happens for CBOR type 0 > INT64_MAX so it is
1660 // always an overflow.
1661 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1662 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001663 break;
1664
1665 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001666 case QCBOR_TYPE_FLOAT:
1667#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001668 {
1669 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001670 // conversion to an int64_t to be able to detect doubles that
1671 // are too large to fit into an int64_t. A double has 52
1672 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1673 // to a double actually causes a round up which is bad and
1674 // wrong for the comparison because it will allow conversion
1675 // of doubles that can't fit into a uint64_t. To remedy this
1676 // INT64_MAX - 0x7ff is used as the cutoff point because if
1677 // that value rounds up in conversion to double it will still
1678 // be less than INT64_MAX. 0x7ff is picked because it has 11
1679 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001680 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001681 // INT64_MAX seconds is on the order of 10 billion years, and
1682 // the earth is less than 5 billion years old, so for most
1683 // uses this conversion error won't occur even though doubles
1684 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001685 //
1686 // Without the 0x7ff there is a ~30 minute range of time
1687 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001688 // where this code would go wrong. Some compilers
1689 // will generate warnings or errors without the 0x7ff
1690 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001691 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1692 pDecodedItem->val.dfnum :
1693 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001694 if(isnan(d) ||
1695 d > (double)(INT64_MAX - 0x7ff) ||
1696 d < (double)(INT64_MIN + 0x7ff)) {
1697 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001698 goto Done;
1699 }
1700 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001701 pDecodedItem->val.epochDate.fSecondsFraction =
1702 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001703 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001704#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001705
Laurence Lundbladec7114722020-08-13 05:11:40 -07001706 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001707 goto Done;
1708
Laurence Lundblade9682a532020-06-06 18:33:04 -07001709#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001710 break;
1711
1712 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001713 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001714 goto Done;
1715 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001716
Laurence Lundblade59289e52019-12-30 13:44:37 -08001717 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1718
1719Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001720 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001721}
1722
1723
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001724/*
1725 Mostly just assign the right data type for the bignum.
1726 */
1727inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1728{
1729 // Stack Use: UsefulBuf 1 -- 16
1730 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1731 return QCBOR_ERR_BAD_OPT_TAG;
1732 }
1733 const UsefulBufC Temp = pDecodedItem->val.string;
1734 pDecodedItem->val.bigNum = Temp;
1735 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1736 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1737 : QCBOR_TYPE_NEGBIGNUM);
1738 return QCBOR_SUCCESS;
1739}
1740
1741
Laurence Lundblade59289e52019-12-30 13:44:37 -08001742#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1743/*
1744 Decode decimal fractions and big floats.
1745
1746 When called pDecodedItem must be the array that is tagged as a big
1747 float or decimal fraction, the array that has the two members, the
1748 exponent and mantissa.
1749
1750 This will fetch and decode the exponent and mantissa and put the
1751 result back into pDecodedItem.
1752 */
1753inline static QCBORError
1754QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1755{
1756 QCBORError nReturn;
1757
1758 // --- Make sure it is an array; track nesting level of members ---
1759 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1760 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1761 goto Done;
1762 }
1763
1764 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001765 // definite length arrays, but not for indefnite. Instead remember
1766 // the nesting level the two integers must be at, which is one
1767 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001768 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1769
1770 // --- Is it a decimal fraction or a bigfloat? ---
1771 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1772 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1773
1774 // --- Get the exponent ---
1775 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001776 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001777 if(nReturn != QCBOR_SUCCESS) {
1778 goto Done;
1779 }
1780 if(exponentItem.uNestingLevel != nNestLevel) {
1781 // Array is empty or a map/array encountered when expecting an int
1782 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1783 goto Done;
1784 }
1785 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1786 // Data arriving as an unsigned int < INT64_MAX has been converted
1787 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1788 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1789 // will be too large for this to handle and thus an error that will
1790 // get handled in the next else.
1791 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1792 } else {
1793 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1794 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1795 goto Done;
1796 }
1797
1798 // --- Get the mantissa ---
1799 QCBORItem mantissaItem;
1800 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1801 if(nReturn != QCBOR_SUCCESS) {
1802 goto Done;
1803 }
1804 if(mantissaItem.uNestingLevel != nNestLevel) {
1805 // Mantissa missing or map/array encountered when expecting number
1806 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1807 goto Done;
1808 }
1809 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1810 // Data arriving as an unsigned int < INT64_MAX has been converted
1811 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1812 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1813 // will be too large for this to handle and thus an error that
1814 // will get handled in an else below.
1815 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1816 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1817 // Got a good big num mantissa
1818 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1819 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001820 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1821 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1822 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001823 } else {
1824 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1825 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1826 goto Done;
1827 }
1828
1829 // --- Check that array only has the two numbers ---
1830 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001831 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001832 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1833 goto Done;
1834 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001835 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001836
1837Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001838 return nReturn;
1839}
1840#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1841
1842
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001843inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1844{
1845 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1846 return QCBOR_ERR_BAD_OPT_TAG;
1847 }
1848 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1849 return QCBOR_SUCCESS;
1850}
1851
1852
1853inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1854{
1855 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1856 return QCBOR_ERR_BAD_OPT_TAG;
1857 }
1858 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001859
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001860 return QCBOR_SUCCESS;
1861}
1862
1863
1864inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1865{
1866 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1867 return QCBOR_ERR_BAD_OPT_TAG;
1868 }
1869 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001870
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001871 return QCBOR_SUCCESS;
1872}
1873
1874
1875inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1876{
1877 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1878 return QCBOR_ERR_BAD_OPT_TAG;
1879 }
1880 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001881
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001882 return QCBOR_SUCCESS;
1883}
1884
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001885
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001886inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1887{
1888 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1889 return QCBOR_ERR_BAD_OPT_TAG;
1890 }
1891 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001892
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001893 return QCBOR_SUCCESS;
1894}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001895
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001896
1897inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1898{
1899 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1900 return QCBOR_ERR_BAD_OPT_TAG;
1901 }
1902 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001903
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001904 return QCBOR_SUCCESS;
1905}
1906
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001907
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001908inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1909{
1910 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1911 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001912 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001913 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1914 } else {
1915 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001916
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001917 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001918
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001919 return QCBOR_SUCCESS;
1920}
1921
1922
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001923inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1924{
1925 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1926 return QCBOR_ERR_BAD_OPT_TAG;
1927 }
1928 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001929
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001930 return QCBOR_SUCCESS;
1931}
1932
1933
Laurence Lundblade59289e52019-12-30 13:44:37 -08001934/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001935 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001936 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001937QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001938QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001939{
1940 QCBORError nReturn;
1941
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001942 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001943 if(nReturn != QCBOR_SUCCESS) {
1944 goto Done;
1945 }
1946
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001947 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001948 switch(pDecodedItem->uTags[i]) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001949
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001950 // Many of the functions here only just map a CBOR tag to
1951 // a QCBOR_TYPE for a string and could probably be
1952 // implemented with less object code. This implementation
1953 // of string types takes about 120 bytes of object code
1954 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001955 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001956 nReturn = DecodeDateString(pDecodedItem);
1957 break;
1958
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001959 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001960 nReturn = DecodeDateEpoch(pDecodedItem);
1961 break;
1962
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001963 case CBOR_TAG_POS_BIGNUM:
1964 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001965 nReturn = DecodeBigNum(pDecodedItem);
1966 break;
1967
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001968 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1969 case CBOR_TAG_DECIMAL_FRACTION:
1970 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001971 // For aggregate tagged types, what goes into pTags is only collected
1972 // from the surrounding data item, not the contents, so pTags is not
1973 // passed on here.
1974
1975 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1976 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001977 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001978
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001979 case CBOR_TAG_CBOR:
1980 nReturn = DecodeWrappedCBOR(pDecodedItem);
1981 break;
1982
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001983 case CBOR_TAG_CBOR_SEQUENCE:
1984 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1985 break;
1986
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001987 case CBOR_TAG_URI:
1988 nReturn = DecodeURI(pDecodedItem);
1989 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001990
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001991 case CBOR_TAG_B64URL:
1992 nReturn = DecodeB64URL(pDecodedItem);
1993 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001994
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001995 case CBOR_TAG_B64:
1996 nReturn = DecodeB64(pDecodedItem);
1997 break;
1998
1999 case CBOR_TAG_MIME:
2000 case CBOR_TAG_BINARY_MIME:
2001 nReturn = DecodeMIME(pDecodedItem);
2002 break;
2003
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002004 case CBOR_TAG_REGEX:
2005 nReturn = DecodeRegex(pDecodedItem);
2006 break;
2007
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002008 case CBOR_TAG_BIN_UUID:
2009 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002010 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002011
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002012 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002013 // The end of the tag list or no tags
2014 // Successful exit from the loop.
2015 goto Done;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002016
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002017 default:
2018 // A tag that is not understood
2019 // A successful exit from the loop
2020 goto Done;
2021
2022 }
2023 if(nReturn != QCBOR_SUCCESS) {
2024 goto Done;
2025 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002026 // A tag was successfully processed, shift it
2027 // out of the list of tags returned.
2028 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002029 }
2030
2031Done:
2032 if(nReturn != QCBOR_SUCCESS) {
2033 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2034 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2035 }
2036 return nReturn;
2037}
2038
2039
2040/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002041 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002042 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002043void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2044{
2045 if(pMe->uLastError != QCBOR_SUCCESS) {
2046 return;
2047 }
2048
2049 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2050}
2051
2052
2053/*
2054 Public function, see header qcbor/qcbor_decode.h file
2055 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002056QCBORError
2057QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2058 QCBORItem *pDecodedItem,
2059 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002060{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002061 QCBORError nReturn;
2062
2063 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2064 if(nReturn != QCBOR_SUCCESS) {
2065 return nReturn;
2066 }
2067
2068 if(pTags != NULL) {
2069 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002070 // Reverse the order because pTags is reverse of
2071 // QCBORItem.uTags.
2072 for(int i = QCBOR_MAX_TAGS_PER_ITEM-1; i >=0 ; i--) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002073 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002074 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002075 }
2076 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2077 return QCBOR_ERR_TOO_MANY_TAGS;
2078 }
2079 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
2080 pTags->uNumUsed++;
2081 }
2082 }
2083
2084 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002085}
2086
2087
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002088/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302089 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302090 next one down. If a layer has no work to do for a particular item
2091 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002092
Laurence Lundblade59289e52019-12-30 13:44:37 -08002093 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2094 tagged data items, turning them into the local C representation.
2095 For the most simple it is just associating a QCBOR_TYPE with the data. For
2096 the complex ones that an aggregate of data items, there is some further
2097 decoding and a little bit of recursion.
2098
2099 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302100 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302101 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002102 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002103
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302104 - GetNext_MapEntry -- This handles the combining of two
2105 items, the label and the data, that make up a map entry.
2106 It only does work on maps. It combines the label and data
2107 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002108
Laurence Lundblade59289e52019-12-30 13:44:37 -08002109 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2110 tags into bit flags associated with the data item. No actual decoding
2111 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002112
Laurence Lundblade59289e52019-12-30 13:44:37 -08002113 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302114 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302115 string allocater to create contiguous space for the item. It
2116 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002117
Laurence Lundblade59289e52019-12-30 13:44:37 -08002118 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2119 atomic data item has a "major type", an integer "argument" and optionally
2120 some content. For text and byte strings, the content is the bytes
2121 that make up the string. These are the smallest data items that are
2122 considered to be well-formed. The content may also be other data items in
2123 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002124
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002125 Roughly this takes 300 bytes of stack for vars. Need to
2126 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002127
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302128 */
2129
2130
2131/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002132 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002133 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002134bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002135 const QCBORItem *pItem,
2136 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002137{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002138 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002139 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002140 break;
2141 }
2142 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002143 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002144 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002145 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002146
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002147 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002148}
2149
2150
2151/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002152 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002153 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002154QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002155{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002156 QCBORError uReturn = me->uLastError;
2157
2158 if(uReturn != QCBOR_SUCCESS) {
2159 goto Done;
2160 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002161
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002162 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002163 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002164 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002165 goto Done;
2166 }
2167
2168 // Error out if not all the bytes are consumed
2169 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002170 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002171 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002172
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002173Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302174 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002175 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002176 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002177
Laurence Lundblade085d7952020-07-24 10:26:30 -07002178 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002179}
2180
2181
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002182/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002183 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002184*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002185// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002186uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2187 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002188 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002189{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002190 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2191 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002192 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002193 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002194 }
2195}
2196
Laurence Lundblade9b334962020-08-27 10:55:53 -07002197/*
2198 Public function, see header qcbor/qcbor_decode.h file
2199*/
2200uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2201 uint32_t uIndex)
2202{
2203 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2204 return CBOR_TAG_INVALID64;
2205 } else {
2206 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2207 }
2208}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002209
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002210/*
2211
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002212Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002213
Laurence Lundbladeee851742020-01-08 08:37:05 -08002214 - Hit end of input before it was expected while decoding type and
2215 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002216
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002217 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002218
Laurence Lundbladeee851742020-01-08 08:37:05 -08002219 - Hit end of input while decoding a text or byte string
2220 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002221
Laurence Lundbladeee851742020-01-08 08:37:05 -08002222 - Encountered conflicting tags -- e.g., an item is tagged both a date
2223 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002224
Laurence Lundbladeee851742020-01-08 08:37:05 -08002225 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002226 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002227
Laurence Lundbladeee851742020-01-08 08:37:05 -08002228 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002229 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002230
Laurence Lundbladeee851742020-01-08 08:37:05 -08002231 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2232 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002233
Laurence Lundbladeee851742020-01-08 08:37:05 -08002234 - The type of a map label is not a string or int
2235 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002236
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002237 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002238
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002239 */
2240
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002241
2242
Laurence Lundbladef6531662018-12-04 10:42:22 +09002243
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002244/* ===========================================================================
2245 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002246
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002247 This implements a simple sting allocator for indefinite length
2248 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2249 implements the function type QCBORStringAllocate and allows easy
2250 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002251
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002252 This particular allocator is built-in for convenience. The caller
2253 can implement their own. All of this following code will get
2254 dead-stripped if QCBORDecode_SetMemPool() is not called.
2255
2256 This is a very primitive memory allocator. It does not track
2257 individual allocations, only a high-water mark. A free or
2258 reallocation must be of the last chunk allocated.
2259
2260 The size of the pool and offset to free memory are packed into the
2261 first 8 bytes of the memory pool so we don't have to keep them in
2262 the decode context. Since the address of the pool may not be
2263 aligned, they have to be packed and unpacked as if they were
2264 serialized data of the wire or such.
2265
2266 The sizes packed in are uint32_t to be the same on all CPU types
2267 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002268 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002269
2270
Laurence Lundbladeee851742020-01-08 08:37:05 -08002271static inline int
2272MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002273{
2274 // Use of UsefulInputBuf is overkill, but it is convenient.
2275 UsefulInputBuf UIB;
2276
Laurence Lundbladeee851742020-01-08 08:37:05 -08002277 // Just assume the size here. It was checked during SetUp so
2278 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002279 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2280 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2281 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2282 return UsefulInputBuf_GetError(&UIB);
2283}
2284
2285
Laurence Lundbladeee851742020-01-08 08:37:05 -08002286static inline int
2287MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002288{
2289 // Use of UsefulOutBuf is overkill, but convenient. The
2290 // length check performed here is useful.
2291 UsefulOutBuf UOB;
2292
2293 UsefulOutBuf_Init(&UOB, Pool);
2294 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2295 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2296 return UsefulOutBuf_GetError(&UOB);
2297}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002298
2299
2300/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002301 Internal function for an allocation, reallocation free and destuct.
2302
2303 Having only one function rather than one each per mode saves space in
2304 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002305
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002306 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2307 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002308static UsefulBuf
2309MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002310{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002311 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002312
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002313 uint32_t uPoolSize;
2314 uint32_t uFreeOffset;
2315
2316 if(uNewSize > UINT32_MAX) {
2317 // This allocator is only good up to 4GB. This check should
2318 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2319 goto Done;
2320 }
2321 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2322
2323 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2324 goto Done;
2325 }
2326
2327 if(uNewSize) {
2328 if(pMem) {
2329 // REALLOCATION MODE
2330 // Calculate pointer to the end of the memory pool. It is
2331 // assumed that pPool + uPoolSize won't wrap around by
2332 // assuming the caller won't pass a pool buffer in that is
2333 // not in legitimate memory space.
2334 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2335
2336 // Check that the pointer for reallocation is in the range of the
2337 // pool. This also makes sure that pointer math further down
2338 // doesn't wrap under or over.
2339 if(pMem >= pPool && pMem < pPoolEnd) {
2340 // Offset to start of chunk for reallocation. This won't
2341 // wrap under because of check that pMem >= pPool. Cast
2342 // is safe because the pool is always less than UINT32_MAX
2343 // because of check in QCBORDecode_SetMemPool().
2344 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2345
2346 // Check to see if the allocation will fit. uPoolSize -
2347 // uMemOffset will not wrap under because of check that
2348 // pMem is in the range of the uPoolSize by check above.
2349 if(uNewSize <= uPoolSize - uMemOffset) {
2350 ReturnValue.ptr = pMem;
2351 ReturnValue.len = uNewSize;
2352
2353 // Addition won't wrap around over because uNewSize was
2354 // checked to be sure it is less than the pool size.
2355 uFreeOffset = uMemOffset + uNewSize32;
2356 }
2357 }
2358 } else {
2359 // ALLOCATION MODE
2360 // uPoolSize - uFreeOffset will not underflow because this
2361 // pool implementation makes sure uFreeOffset is always
2362 // smaller than uPoolSize through this check here and
2363 // reallocation case.
2364 if(uNewSize <= uPoolSize - uFreeOffset) {
2365 ReturnValue.len = uNewSize;
2366 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002367 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002368 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002369 }
2370 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002371 if(pMem) {
2372 // FREE MODE
2373 // Cast is safe because of limit on pool size in
2374 // QCBORDecode_SetMemPool()
2375 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2376 } else {
2377 // DESTRUCT MODE
2378 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002379 }
2380 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002381
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002382 UsefulBuf Pool = {pPool, uPoolSize};
2383 MemPool_Pack(Pool, uFreeOffset);
2384
2385Done:
2386 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002387}
2388
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002389
Laurence Lundbladef6531662018-12-04 10:42:22 +09002390/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002391 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002392 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002393QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2394 UsefulBuf Pool,
2395 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002396{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002397 // The pool size and free mem offset are packed into the beginning
2398 // of the pool memory. This compile time check make sure the
2399 // constant in the header is correct. This check should optimize
2400 // down to nothing.
2401 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002402 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002403 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002404
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002405 // The pool size and free offset packed in to the beginning of pool
2406 // memory are only 32-bits. This check will optimize out on 32-bit
2407 // machines.
2408 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002409 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002410 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002411
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002412 // This checks that the pool buffer given is big enough.
2413 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
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 pMe->StringAllocator.pfAllocator = MemPool_Function;
2418 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2419 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002420
Laurence Lundblade30816f22018-11-10 13:40:22 +07002421 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002422}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002423
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002424
2425
Laurence Lundblade9b334962020-08-27 10:55:53 -07002426static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2427{
2428 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2429}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002430
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002431
2432/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002433 Consume an entire map or array (and do next to
2434 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002435 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002436static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002437ConsumeItem(QCBORDecodeContext *pMe,
2438 const QCBORItem *pItemToConsume,
2439 uint_fast8_t *puNextNestLevel)
2440{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002441 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002442 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002443
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002444 // If it is a map or array, this will tell if it is empty.
2445 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2446
2447 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2448 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002449
Laurence Lundblade1341c592020-04-11 14:19:05 -07002450 /* This works for definite and indefinite length
2451 * maps and arrays by using the nesting level
2452 */
2453 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002454 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002455 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002456 goto Done;
2457 }
2458 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002459
Laurence Lundblade1341c592020-04-11 14:19:05 -07002460 if(puNextNestLevel != NULL) {
2461 *puNextNestLevel = Item.uNextNestLevel;
2462 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002463 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002464
Laurence Lundblade1341c592020-04-11 14:19:05 -07002465 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002466 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002467 if(puNextNestLevel != NULL) {
2468 /* Just pass the nesting level through */
2469 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2470 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002471 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002472 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002473
2474Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002475 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002476}
2477
2478
Laurence Lundblade1341c592020-04-11 14:19:05 -07002479/* Return true if the labels in Item1 and Item2 are the same.
2480 Works only for integer and string labels. Returns false
2481 for any other type. */
2482static inline bool
2483MatchLabel(QCBORItem Item1, QCBORItem Item2)
2484{
2485 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2486 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2487 return true;
2488 }
2489 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002490 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002491 return true;
2492 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002493 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002494 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2495 return true;
2496 }
2497 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2498 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2499 return true;
2500 }
2501 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002502
Laurence Lundblade1341c592020-04-11 14:19:05 -07002503 /* Other label types are never matched */
2504 return false;
2505}
2506
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002507
2508/*
2509 Returns true if Item1 and Item2 are the same type
2510 or if either are of QCBOR_TYPE_ANY.
2511 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002512static inline bool
2513MatchType(QCBORItem Item1, QCBORItem Item2)
2514{
2515 if(Item1.uDataType == Item2.uDataType) {
2516 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002517 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002518 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002519 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002520 return true;
2521 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002522 return false;
2523}
2524
2525
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002526/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002527 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002528
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002529 @param[in] pMe The decode context to search.
2530 @param[in,out] pItemArray The items to search for and the items found.
2531 @param[out] puOffset Byte offset of last item matched.
2532 @param[in] pCBContext Context for the not-found item call back.
2533 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002534
2535 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2536
Laurence Lundblade9b334962020-08-27 10:55:53 -07002537 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label) were found
2538 for one of the labels being search for. This duplicate detection is only performed for items in pItemArray,
2539 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002540
2541 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2542
2543 @retval Also errors returned by QCBORDecode_GetNext().
2544
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002545 On input pItemArray contains a list of labels and data types
2546 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002547
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002548 On output the fully retrieved items are filled in with
2549 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002550
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002551 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002552 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002553// TODO: make this handle indefinite length strings, possibly with
2554// allocation only when returning the string.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002555static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002556MapSearch(QCBORDecodeContext *pMe,
2557 QCBORItem *pItemArray,
2558 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002559 void *pCBContext,
2560 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002561{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002562 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002563 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002564
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002565 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002566 uReturn = pMe->uLastError;
2567 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002568 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002569
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002570 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002571 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2572 /* QCBOR_TYPE_NONE as first item indicates just looking
2573 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002574 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2575 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002576 }
2577
Laurence Lundblade085d7952020-07-24 10:26:30 -07002578 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2579 // It is an empty bounded array or map
2580 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2581 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002582 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002583 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002584 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002585 // Nothing is ever found in an empty array or map. All items
2586 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002587 uReturn = QCBOR_SUCCESS;
2588 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002589 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002590 }
2591
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002592 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002593 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2594
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002595 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002596 UsefulInputBuf_Seek(&(pMe->InBuf),
2597 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002598
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002599 /*
2600 Loop over all the items in the map. They could be
2601 deeply nested and this should handle both definite
2602 and indefinite length maps and arrays, so this
2603 adds some complexity.
2604 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002605 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002606 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002607 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002608 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002609 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002610
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002611 /* Get the item */
2612 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002613 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002614 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002615 /* Got non-well-formed CBOR so map can't even be decoded. */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002616 goto Done;
2617 }
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002618 if(uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
2619 // Unexpected end of map or array.
2620 goto Done;
2621 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002622
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002623 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002624 bool bMatched = false;
2625 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
Laurence Lundblade4b270642020-08-14 12:53:07 -07002626 // TODO: have label filled in on invalid CBOR so error reporting
Laurence Lundblade9b334962020-08-27 10:55:53 -07002627 // can work a lot better.
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002628 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002629 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002630 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2631 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002632 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002633 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002634 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002635 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002636 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002637 goto Done;
2638 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002639
Laurence Lundblade1341c592020-04-11 14:19:05 -07002640 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002641 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002642 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002643 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002644 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002645 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002646 bMatched = true;
2647 }
2648 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002649
2650
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002651 if(!bMatched && pfCallback != NULL) {
2652 /*
2653 Call the callback on unmatched labels.
2654 (It is tempting to do duplicate detection here, but that would
2655 require dynamic memory allocation because the number of labels
2656 that might be encountered is unbounded.)
2657 */
2658 uReturn = (*pfCallback)(pCBContext, &Item);
2659 if(uReturn != QCBOR_SUCCESS) {
2660 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002661 }
2662 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002663
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002664 /*
2665 Consume the item whether matched or not. This
2666 does the work of traversing maps and array and
2667 everything in them. In this loop only the
2668 items at the current nesting level are examined
2669 to match the labels.
2670 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002671 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002672 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002673 goto Done;
2674 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002675
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002676 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002677
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002678 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002679
2680 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002681
2682 // Check here makes that this won't accidentally be
2683 // QCBOR_MAP_OFFSET_CACHE_INVALID. It is larger than
2684 // QCBOR_MAX_DECODE_INPUT_SIZE.
2685 if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
2686 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2687 goto Done;
2688 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002689 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2690 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002691
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002692 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002693 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2694
2695 Done2:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002696 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
2697 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002698 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002699 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002700 }
2701 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002702
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002703 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002704}
2705
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002706
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002707/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002708 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002709*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002710void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2711 int64_t nLabel,
2712 uint8_t uQcborType,
2713 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002714{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002715 if(pMe->uLastError != QCBOR_SUCCESS) {
2716 return;
2717 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002718
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002719 QCBORItem OneItemSeach[2];
2720 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2721 OneItemSeach[0].label.int64 = nLabel;
2722 OneItemSeach[0].uDataType = uQcborType;
2723 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002724
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002725 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2726 if(uReturn != QCBOR_SUCCESS) {
2727 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002728 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002729 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002730 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002731 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002732 }
2733
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002734 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002735
2736 Done:
2737 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002738}
2739
2740
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002741/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002742 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002743*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002744void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2745 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002746 uint8_t uQcborType,
2747 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002748{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002749 if(pMe->uLastError != QCBOR_SUCCESS) {
2750 return;
2751 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002752
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002753 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002754 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2755 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2756 OneItemSeach[0].uDataType = uQcborType;
2757 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002758
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002759 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2760 if(uReturn != QCBOR_SUCCESS) {
2761 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002762 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002763 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002764 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002765 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002766 }
2767
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002768 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002769
2770Done:
2771 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002772}
2773
2774
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002775
Laurence Lundblade9b334962020-08-27 10:55:53 -07002776static QCBORError CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002777{
2778 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2779 if(uDataType == puTypeList[i]) {
2780 return QCBOR_SUCCESS;
2781 }
2782 }
2783 return QCBOR_ERR_UNEXPECTED_TYPE;
2784}
2785
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002786
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002787/**
2788 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002789 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002790
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002791 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2792 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002793
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002794 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2795 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002796static QCBORError CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002797{
2798 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2799 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2800 /* There are tags that QCBOR couldn't process on this item and
2801 the caller has told us there should not be. */
2802 return QCBOR_ERR_UNEXPECTED_TYPE;
2803 }
2804
2805 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2806 const int nItemType = pItem->uDataType;
2807
2808 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2809 // Must match the tag and only the tag
2810 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2811 }
2812
2813 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2814 if(uReturn == QCBOR_SUCCESS) {
2815 return QCBOR_SUCCESS;
2816 }
2817
2818 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2819 /* Must match the content type and only the content type.
2820 There was no match just above so it is a fail. */
2821 return QCBOR_ERR_UNEXPECTED_TYPE;
2822 }
2823
2824 /* If here it can match either the tag or the content
2825 and it hasn't matched the content, so the end
2826 result is whether it matches the tag. This is
2827 also the case that the CBOR standard discourages. */
2828
2829 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2830}
2831
Laurence Lundblade9b334962020-08-27 10:55:53 -07002832
Laurence Lundblade9b334962020-08-27 10:55:53 -07002833
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002834// This could be semi-private if need be
2835static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002836void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2837 int64_t nLabel,
2838 TagSpecification TagSpec,
2839 QCBORItem *pItem)
2840{
2841 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2842 if(pMe->uLastError != QCBOR_SUCCESS) {
2843 return;
2844 }
2845
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002846 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002847}
2848
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002849
2850// This could be semi-private if need be
2851static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002852void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2853 const char *szLabel,
2854 TagSpecification TagSpec,
2855 QCBORItem *pItem)
2856{
2857 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2858 if(pMe->uLastError != QCBOR_SUCCESS) {
2859 return;
2860 }
2861
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002862 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002863}
2864
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002865// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002866void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2867 int64_t nLabel,
2868 TagSpecification TagSpec,
2869 UsefulBufC *pString)
2870{
2871 QCBORItem Item;
2872 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2873 if(pMe->uLastError == QCBOR_SUCCESS) {
2874 *pString = Item.val.string;
2875 }
2876}
2877
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002878// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002879void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2880 const char * szLabel,
2881 TagSpecification TagSpec,
2882 UsefulBufC *pString)
2883{
2884 QCBORItem Item;
2885 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2886 if(pMe->uLastError == QCBOR_SUCCESS) {
2887 *pString = Item.val.string;
2888 }
2889}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002890
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002891/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002892 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002893*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002894void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002895{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002896 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2897 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002898}
2899
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002900/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002901 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002902*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002903void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2904 QCBORItem *pItemList,
2905 void *pCallbackCtx,
2906 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002907{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002908 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2909 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002910}
2911
2912
Laurence Lundblade34691b92020-05-18 22:25:25 -07002913static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002914{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002915 // The first item in pSearch is the one that is to be
2916 // entered. It should be the only one filled in. Any other
2917 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07002918 if(pMe->uLastError != QCBOR_SUCCESS) {
2919 // Already in error state; do nothing.
2920 return;
2921 }
2922
2923 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002924 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002925 if(pMe->uLastError != QCBOR_SUCCESS) {
2926 return;
2927 }
2928
Laurence Lundblade9b334962020-08-27 10:55:53 -07002929 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002930 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002931 return;
2932 }
2933
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002934 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002935 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002936
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002937 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002938 be at the right place.
2939
2940 The UsefulInBuf offset could be anywhere, so no assumption is
2941 made about it.
2942
2943 No assumption is made about the pre-order nesting level either.
2944
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002945 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002946 the map level that is being entered.
2947 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002948 /* Seek to the data item that is the map or array */
2949 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002950
2951 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002952
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002953 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002954}
2955
2956
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002957/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002958 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002959*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002960void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002961{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002962 QCBORItem OneItemSeach[2];
2963 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2964 OneItemSeach[0].label.int64 = nLabel;
2965 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2966 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002967
Laurence Lundblade9b334962020-08-27 10:55:53 -07002968 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002969 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002970}
2971
2972
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002973/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002974 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002975*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002976void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002977{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002978 QCBORItem OneItemSeach[2];
2979 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2980 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2981 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2982 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002983
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002984 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002985}
2986
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002987/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002988 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002989*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002990void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002991{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002992 QCBORItem OneItemSeach[2];
2993 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2994 OneItemSeach[0].label.int64 = nLabel;
2995 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2996 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002997
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002998 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002999}
3000
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003001/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003002 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003003*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003004void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3005{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003006 QCBORItem OneItemSeach[2];
3007 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3008 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3009 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3010 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003011
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003012 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003013}
3014
3015
Laurence Lundblade02625d42020-06-25 14:41:41 -07003016// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003017void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003018{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003019 QCBORError uErr;
3020
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003021 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003022 if(pMe->uLastError != QCBOR_SUCCESS) {
3023 // Already in error state; do nothing.
3024 return;
3025 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003026
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003027 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003028 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003029 uErr = QCBORDecode_GetNext(pMe, &Item);
3030 if(uErr != QCBOR_SUCCESS) {
3031 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003032 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003033 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003034 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3035 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003036 }
3037
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003038 CopyTags(pMe, &Item);
3039
3040
Laurence Lundbladef0499502020-08-01 11:55:57 -07003041 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003042 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003043 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3044 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003045 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003046 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3047 }
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003048 // Special case to increment nesting level for zero-length maps and arrays entered in bounded mode.
3049 DecodeNesting_Descend(&(pMe->nesting), uType);
3050 }
3051
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003052 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003053
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003054 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3055 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003056
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003057Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003058 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003059}
3060
Laurence Lundblade02625d42020-06-25 14:41:41 -07003061
3062/*
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003063 This is the common work for exiting a level that is a bounded map, array or bstr
3064 wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003065
3066 One chunk of work is to set up the pre-order traversal so it is at
3067 the item just after the bounded map, array or bstr that is being
3068 exited. This is somewhat complex.
3069
3070 The other work is to level-up the bounded mode to next higest bounded
3071 mode or the top level if there isn't one.
3072 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003073static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003074ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003075{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003076 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003077
Laurence Lundblade02625d42020-06-25 14:41:41 -07003078 /*
3079 First the pre-order-traversal byte offset is positioned to the
3080 item just after the bounded mode item that was just consumed.
3081 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003082 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3083
Laurence Lundblade02625d42020-06-25 14:41:41 -07003084 /*
3085 Next, set the current nesting level to one above the bounded level
3086 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003087
Laurence Lundblade02625d42020-06-25 14:41:41 -07003088 DecodeNesting_CheckBoundedType() is always called before this and
3089 makes sure pCurrentBounded is valid.
3090 */
3091 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3092
3093 /*
3094 This does the complex work of leveling up the pre-order traversal
3095 when the end of a map or array or another bounded level is
3096 reached. It may do nothing, or ascend all the way to the top
3097 level.
3098 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003099 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003100 if(uErr != QCBOR_SUCCESS) {
3101 goto Done;
3102 }
3103
Laurence Lundblade02625d42020-06-25 14:41:41 -07003104 /*
3105 This makes the next highest bounded level the current bounded
3106 level. If there is no next highest level, then no bounded mode is
3107 in effect.
3108 */
3109 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003110
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003111 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003112
3113Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003114 return uErr;
3115}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003116
Laurence Lundblade02625d42020-06-25 14:41:41 -07003117
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003118// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003119void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003120{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003121 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003122 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003123 return;
3124 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003125
Laurence Lundblade02625d42020-06-25 14:41:41 -07003126 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003127
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003128 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003129 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003130 goto Done;
3131 }
3132
Laurence Lundblade02625d42020-06-25 14:41:41 -07003133 /*
3134 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003135 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003136 from previous map search, then do a dummy search.
3137 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003138 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003139 QCBORItem Dummy;
3140 Dummy.uLabelType = QCBOR_TYPE_NONE;
3141 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3142 if(uErr != QCBOR_SUCCESS) {
3143 goto Done;
3144 }
3145 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003146
Laurence Lundblade02625d42020-06-25 14:41:41 -07003147 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003148
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003149Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003150 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003151}
3152
3153
Laurence Lundblade1341c592020-04-11 14:19:05 -07003154
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003155static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003156 const QCBORItem *pItem,
3157 uint8_t uTagRequirement,
3158 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003159{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003160 if(pBstr) {
3161 *pBstr = NULLUsefulBufC;
3162 }
3163
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003164 if(pMe->uLastError != QCBOR_SUCCESS) {
3165 // Already in error state; do nothing.
3166 return pMe->uLastError;
3167 }
3168
3169 QCBORError uError = QCBOR_SUCCESS;
3170
3171 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3172 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3173 goto Done;;
3174 }
3175
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003176 const TagSpecification TagSpec =
3177 {
3178 uTagRequirement,
3179 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3180 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3181 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003182
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003183 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003184 if(uError != QCBOR_SUCCESS) {
3185 goto Done;
3186 }
3187
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003188 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003189 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07003190 so the increment in NestLevelAscender called by ExitBoundedLevel()
3191 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003192 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003193 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003194
3195 if(pBstr) {
3196 *pBstr = pItem->val.string;
3197 }
3198
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003199 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003200
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003201 // Need to move UIB input cursor to the right place.
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003202 // Most of these calls are simple inline accessors so this doesn't
3203 // amount to much code. There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003204 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003205 if(uEndOfBstr >= QCBOR_MAX_DECODE_INPUT_SIZE || uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003206 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003207 goto Done;
3208 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003209 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003210 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003211
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003212 // Casts are OK because of checks against QCBOR_MAX_DECODE_INPUT_SIZE above.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003213 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003214 (uint32_t)uPreviousLength,
3215 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003216Done:
3217 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003218}
3219
3220
Laurence Lundblade02625d42020-06-25 14:41:41 -07003221/*
3222 Public function, see header qcbor/qcbor_decode.h file
3223 */
3224void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003225 uint8_t uTagRequirement,
3226 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003227{
3228 if(pMe->uLastError != QCBOR_SUCCESS) {
3229 // Already in error state; do nothing.
3230 return;
3231 }
3232
3233 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003234 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003235 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3236 if(pMe->uLastError != QCBOR_SUCCESS) {
3237 return;
3238 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003239
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003240 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003241 &Item,
3242 uTagRequirement,
3243 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003244}
3245
3246
Laurence Lundblade02625d42020-06-25 14:41:41 -07003247/*
3248 Public function, see header qcbor/qcbor_decode.h file
3249 */
3250void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003251 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003252 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003253 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003254{
3255 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003256 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003257
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003258 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003259}
3260
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003261
Laurence Lundblade02625d42020-06-25 14:41:41 -07003262/*
3263 Public function, see header qcbor/qcbor_decode.h file
3264 */
3265void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003266 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003267 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003268 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003269{
3270 QCBORItem Item;
3271 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3272
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003273 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003274}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003275
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003276
Laurence Lundblade02625d42020-06-25 14:41:41 -07003277/*
3278 Public function, see header qcbor/qcbor_decode.h file
3279 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003280void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003281{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003282 if(pMe->uLastError != QCBOR_SUCCESS) {
3283 // Already in error state; do nothing.
3284 return;
3285 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003286
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003287 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003288 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003289 return;
3290 }
3291
3292 /*
3293 Reset the length of the UsefulInputBuf to what it was before
3294 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003295 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003296 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003297 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003298
3299
Laurence Lundblade02625d42020-06-25 14:41:41 -07003300 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003301 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003302}
3303
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003304
Laurence Lundbladee6430642020-03-14 21:15:44 -07003305
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003306
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003307
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003308
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003309
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003310
Laurence Lundblade9b334962020-08-27 10:55:53 -07003311static QCBORError InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003312{
3313 switch(pItem->uDataType) {
3314 case QCBOR_TYPE_TRUE:
3315 *pBool = true;
3316 return QCBOR_SUCCESS;
3317 break;
3318
3319 case QCBOR_TYPE_FALSE:
3320 *pBool = false;
3321 return QCBOR_SUCCESS;
3322 break;
3323
3324 default:
3325 return QCBOR_ERR_UNEXPECTED_TYPE;
3326 break;
3327 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003328 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003329}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003330
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003331
Laurence Lundblade9b334962020-08-27 10:55:53 -07003332
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003333/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003334 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003335*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003336void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003337{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003338 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003339 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003340 return;
3341 }
3342
Laurence Lundbladec4537442020-04-14 18:53:22 -07003343 QCBORError nError;
3344 QCBORItem Item;
3345
3346 nError = QCBORDecode_GetNext(pMe, &Item);
3347 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003348 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003349 return;
3350 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003351 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003352}
3353
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003354
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003355/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003356 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003357*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003358void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003359{
3360 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003361 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003362
Laurence Lundblade9b334962020-08-27 10:55:53 -07003363 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003364}
3365
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003366
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003367/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003368 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003369*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003370void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3371{
3372 QCBORItem Item;
3373 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3374
Laurence Lundblade9b334962020-08-27 10:55:53 -07003375 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003376}
3377
3378
3379
Laurence Lundblade9b334962020-08-27 10:55:53 -07003380/*
3381 A number of methods decode CBOR that is associated with a
3382 specific tag or tags.
Laurence Lundbladec7114722020-08-13 05:11:40 -07003383
Laurence Lundblade9b334962020-08-27 10:55:53 -07003384 The API of the method returns the
3385 data in a way specific to the
3386
3387 No tags at all.
3388
3389
3390 Require tag for the particular type for the method and no other.
3391
3392
3393 Either no tags at all or the particular type for the method and no other.
3394
3395 No tag for particular type; pass other tags along.
3396
3397 Require the tag for the particular type; pass other tags along
3398
3399 Any tagging is OK; consume the tag for the particular type if present,
3400 pass other tags along.
3401
3402
3403 1) REQUIRED
3404- 1 XXXX -- works
3405- T 1 XXX -- works, T is returned
3406
3407 if(tag is of interest) {
3408 process content
3409 return T if present
3410 }
3411
3412
3413 2) FORBIDDEN
3414 - XXX -- works
3415 - T XXX -- ???
3416
3417 if(tag is of interest) {
3418 error out since tag is forbidden
3419 } else {
3420 process contents
3421 return T
3422 }
3423
3424 3) OPTIONAL
3425 - XXX works
3426 - 1 XXX works
3427 - T XXX
3428 - T 1 XXX works, T is returned
3429
3430if (inner tag is of interest) {
3431 process content
3432 return tag T if present
3433 } else if (there is no tag) {
3434 process content
3435 } else {
3436 process content if possible
3437 return T
3438 }
3439
3440A field is type X
3441 - tag for type X is REQUIRED
3442 - tag for type X is FORBIDDEN
3443 - tag for type X is optional
3444 - Other tags are FORBIDDEN
3445 - Other tags are ALLOWED
3446
3447
3448
3449 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003450
3451static void ProcessEpochDate(QCBORDecodeContext *pMe,
3452 QCBORItem *pItem,
3453 uint8_t uTagRequirement,
3454 int64_t *pnTime)
3455{
3456 if(pMe->uLastError != QCBOR_SUCCESS) {
3457 // Already in error state, do nothing
3458 return;
3459 }
3460
3461 QCBORError uErr;
3462
3463 const TagSpecification TagSpec =
3464 {
3465 uTagRequirement,
3466 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3467 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT}
3468 };
3469
Laurence Lundblade4b270642020-08-14 12:53:07 -07003470 // TODO: this will give an unexpected type error instead of
Laurence Lundbladec7114722020-08-13 05:11:40 -07003471 // overflow error for QCBOR_TYPE_UINT64 because TagSpec
3472 // only has three target types.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003473 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003474 if(uErr != QCBOR_SUCCESS) {
3475 goto Done;
3476 }
3477
3478 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3479 uErr = DecodeDateEpoch(pItem);
3480 if(uErr != QCBOR_SUCCESS) {
3481 goto Done;
3482 }
3483 }
3484
Laurence Lundblade9b334962020-08-27 10:55:53 -07003485 // Save the tags in the last item's tags in the decode context
3486 // for QCBORDecode_GetNthTagOfLast()
3487 CopyTags(pMe, pItem);
3488
Laurence Lundbladec7114722020-08-13 05:11:40 -07003489 *pnTime = pItem->val.epochDate.nSeconds;
3490
3491Done:
3492 pMe->uLastError = (uint8_t)uErr;
3493}
3494
3495
3496void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
3497 uint8_t uTagRequirement,
3498 int64_t *pnTime)
3499{
3500 if(pMe->uLastError != QCBOR_SUCCESS) {
3501 // Already in error state, do nothing
3502 return;
3503 }
3504
3505 QCBORItem Item;
3506 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3507
3508 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3509}
3510
3511
3512void
3513QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3514 int64_t nLabel,
3515 uint8_t uTagRequirement,
3516 int64_t *pnTime)
3517{
3518 QCBORItem Item;
3519 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3520 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3521}
3522
3523
3524void
3525QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3526 const char *szLabel,
3527 uint8_t uTagRequirement,
3528 int64_t *pnTime)
3529{
3530 QCBORItem Item;
3531 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3532 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3533}
3534
3535
3536
3537
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003538void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3539 TagSpecification TagSpec,
3540 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003541{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003542 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003543 // Already in error state, do nothing
3544 return;
3545 }
3546
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003547 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003548 QCBORItem Item;
3549
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003550 uError = QCBORDecode_GetNext(pMe, &Item);
3551 if(uError != QCBOR_SUCCESS) {
3552 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003553 return;
3554 }
3555
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003556 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003557
3558 if(pMe->uLastError == QCBOR_SUCCESS) {
3559 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003560 } else {
3561 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003562 }
3563}
3564
Laurence Lundbladec4537442020-04-14 18:53:22 -07003565
3566
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003567
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003568static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003569 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003570 UsefulBufC *pValue,
3571 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003572{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003573 const TagSpecification TagSpec =
3574 {
3575 uTagRequirement,
3576 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3577 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3578 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003579
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003580 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003581 if(uErr != QCBOR_SUCCESS) {
3582 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003583 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003584
3585 *pValue = pItem->val.string;
3586
3587 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3588 *pbIsNegative = false;
3589 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3590 *pbIsNegative = true;
3591 }
3592
3593 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003594}
3595
3596
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003597/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003598 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003599 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003600void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3601 uint8_t uTagRequirement,
3602 UsefulBufC *pValue,
3603 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003604{
3605 if(pMe->uLastError != QCBOR_SUCCESS) {
3606 // Already in error state, do nothing
3607 return;
3608 }
3609
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003610 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003611 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3612 if(uError != QCBOR_SUCCESS) {
3613 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003614 return;
3615 }
3616
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003617 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003618}
3619
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003620
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003621/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003622 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003623*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003624void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3625 int64_t nLabel,
3626 uint8_t uTagRequirement,
3627 UsefulBufC *pValue,
3628 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003629{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003630 QCBORItem Item;
3631 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003632 if(pMe->uLastError != QCBOR_SUCCESS) {
3633 return;
3634 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003635
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003636 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003637}
3638
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003639
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003640/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003641 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003642*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003643void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3644 const char *szLabel,
3645 uint8_t uTagRequirement,
3646 UsefulBufC *pValue,
3647 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003648{
3649 QCBORItem Item;
3650 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003651 if(pMe->uLastError != QCBOR_SUCCESS) {
3652 return;
3653 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003654
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003655 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003656}
3657
3658
3659
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003660
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003661// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003662QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3663 const QCBORItem *pItem,
3664 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003665 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003666{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003667 const TagSpecification TagSpecText =
3668 {
3669 uTagRequirement,
3670 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3671 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3672 };
3673 const TagSpecification TagSpecBinary =
3674 {
3675 uTagRequirement,
3676 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3677 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3678 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003679
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003680 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003681
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003682 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003683 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003684 if(pbIsTag257 != NULL) {
3685 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003686 }
3687 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003688 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003689 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003690 if(pbIsTag257 != NULL) {
3691 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003692 }
3693 uReturn = QCBOR_SUCCESS;
3694
3695 } else {
3696 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3697 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003698
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003699 return uReturn;
3700}
3701
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003702// Improvement: add methods for wrapped CBOR, a simple alternate to EnterBstrWrapped
3703
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003704
3705
3706
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003707#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003708
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003709typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003710
3711
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003712// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003713static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003714{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003715 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003716
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003717 if(uResult != 0) {
3718 /* This loop will run a maximum of 19 times because
3719 * UINT64_MAX < 10 ^^ 19. More than that will cause
3720 * exit with the overflow error
3721 */
3722 for(; nExponent > 0; nExponent--) {
3723 if(uResult > UINT64_MAX / 10) {
3724 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3725 }
3726 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003727 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003728
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003729 for(; nExponent < 0; nExponent++) {
3730 uResult = uResult / 10;
3731 if(uResult == 0) {
3732 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3733 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003734 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003735 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003736 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003737
3738 *puResult = uResult;
3739
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003740 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003741}
3742
3743
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003744// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003745static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003746{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003747 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003748
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003749 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003750
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003751 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003752 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003753 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003754 */
3755 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003756 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003757 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003758 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003759 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003760 nExponent--;
3761 }
3762
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003763 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003764 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003765 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3766 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003767 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003768 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003769 }
3770
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003771 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003772
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003773 return QCBOR_SUCCESS;
3774}
3775
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003776
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003777/*
3778 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3779 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003780static inline QCBORError ExponentiateNN(int64_t nMantissa,
3781 int64_t nExponent,
3782 int64_t *pnResult,
3783 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003784{
3785 uint64_t uResult;
3786
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003787 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003788 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003789 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3790
3791 // Do the exponentiation of the positive mantissa
3792 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3793 if(uReturn) {
3794 return uReturn;
3795 }
3796
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003797
Laurence Lundblade983500d2020-05-14 11:49:34 -07003798 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3799 of INT64_MIN. This assumes two's compliment representation where
3800 INT64_MIN is one increment farther from 0 than INT64_MAX.
3801 Trying to write -INT64_MIN doesn't work to get this because the
3802 compiler tries to work with an int64_t which can't represent
3803 -INT64_MIN.
3804 */
3805 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3806
3807 // Error out if too large
3808 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003809 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3810 }
3811
3812 // Casts are safe because of checks above
3813 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3814
3815 return QCBOR_SUCCESS;
3816}
3817
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003818
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003819/*
3820 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3821 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003822static inline QCBORError ExponentitateNU(int64_t nMantissa,
3823 int64_t nExponent,
3824 uint64_t *puResult,
3825 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003826{
3827 if(nMantissa < 0) {
3828 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3829 }
3830
3831 // Cast to unsigned is OK because of check for negative
3832 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3833 // Exponentiation is straight forward
3834 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3835}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003836
3837
3838/*
3839 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3840 */
3841static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3842 int64_t nExponent,
3843 uint64_t *puResult,
3844 fExponentiator pfExp)
3845{
3846 return (*pfExp)(uMantissa, nExponent, puResult);
3847}
3848
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003849#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3850
3851
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003852
3853
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003854
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003855static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003856{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003857 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003858
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003859 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003860 const uint8_t *pByte = BigNum.ptr;
3861 size_t uLen = BigNum.len;
3862 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003863 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003864 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003865 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003866 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003867 }
3868
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003869 *pResult = uResult;
3870 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003871}
3872
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003873
Laurence Lundblade887add82020-05-17 05:50:34 -07003874static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003875{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003876 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003877}
3878
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003879
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003880static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003881{
3882 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003883 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3884 if(uError) {
3885 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003886 }
3887 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3888 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003889 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003890}
3891
3892
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003893static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003894{
3895 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003896 /* The negative integer furthest from zero for a C int64_t is
3897 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3898 negative number in CBOR is computed as -n - 1 where n is the
3899 encoded integer, where n is what is in the variable BigNum. When
3900 converting BigNum to a uint64_t, the maximum value is thus
3901 INT64_MAX, so that when it -n - 1 is applied to it the result will
3902 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003903
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003904 -n - 1 <= INT64_MIN.
3905 -n - 1 <= -INT64_MAX - 1
3906 n <= INT64_MAX.
3907 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003908 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003909 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003910 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003911 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003912
3913 /// Now apply -n - 1. The cast is safe because
3914 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3915 // is the largest positive integer that an int64_t can
3916 // represent. */
3917 *pnResult = -(int64_t)uResult - 1;
3918
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003919 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003920}
3921
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003922
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003923
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003924
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003925
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003926/*
3927Convert a integers and floats to an int64_t.
3928
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003929\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003930
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003931\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003932
3933\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3934
3935\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3936
3937*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003938static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003939{
3940 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003941 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003942 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003943#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003944 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003945 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3946 http://www.cplusplus.com/reference/cmath/llround/
3947 */
3948 // Not interested in FE_INEXACT
3949 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003950 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3951 *pnValue = llround(pItem->val.dfnum);
3952 } else {
3953 *pnValue = lroundf(pItem->val.fnum);
3954 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003955 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
3956 // llround() shouldn't result in divide by zero, but catch
3957 // it here in case it unexpectedly does. Don't try to
3958 // distinguish between the various exceptions because it seems
3959 // they vary by CPU, compiler and OS.
3960 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003961 }
3962 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003963 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003964 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003965#else
3966 return QCBOR_ERR_HW_FLOAT_DISABLED;
3967#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003968 break;
3969
3970 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003971 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003972 *pnValue = pItem->val.int64;
3973 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003974 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003975 }
3976 break;
3977
3978 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003979 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003980 if(pItem->val.uint64 < INT64_MAX) {
3981 *pnValue = pItem->val.int64;
3982 } else {
3983 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3984 }
3985 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003986 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003987 }
3988 break;
3989
3990 default:
3991 return QCBOR_ERR_UNEXPECTED_TYPE;
3992 }
3993 return QCBOR_SUCCESS;
3994}
3995
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003996
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003997void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003998 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003999 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004000 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004001{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004002 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004003 return;
4004 }
4005
Laurence Lundbladee6430642020-03-14 21:15:44 -07004006 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004007 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4008 if(uError) {
4009 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004010 return;
4011 }
4012
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004013 if(pItem) {
4014 *pItem = Item;
4015 }
4016
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004017 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004018}
4019
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004020
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004021void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4022 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004023 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004024 int64_t *pnValue,
4025 QCBORItem *pItem)
4026{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004027 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004028 if(pMe->uLastError != QCBOR_SUCCESS) {
4029 return;
4030 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004031
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004032 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004033}
4034
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004035
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004036void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4037 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004038 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004039 int64_t *pnValue,
4040 QCBORItem *pItem)
4041{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004042 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004043 if(pMe->uLastError != QCBOR_SUCCESS) {
4044 return;
4045 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004046
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004047 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004048}
4049
4050
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004051/*
4052 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004053
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004054 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004055
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004056 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004057
4058 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4059
4060 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
4061
4062 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004063static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004064{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004065 switch(pItem->uDataType) {
4066
4067 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004068 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004069 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004070 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004071 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004072 }
4073 break;
4074
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004075 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004076 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004077 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004078 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004079 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004080 }
4081 break;
4082
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004083#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4084 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004085 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004086 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004087 pItem->val.expAndMantissa.nExponent,
4088 pnValue,
4089 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004090 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004091 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004092 }
4093 break;
4094
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004095 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004096 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004097 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004098 pItem->val.expAndMantissa.nExponent,
4099 pnValue,
4100 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004101 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004102 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004103 }
4104 break;
4105
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004106 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004107 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004108 int64_t nMantissa;
4109 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004110 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4111 if(uErr) {
4112 return uErr;
4113 }
4114 return ExponentiateNN(nMantissa,
4115 pItem->val.expAndMantissa.nExponent,
4116 pnValue,
4117 Exponentitate10);
4118 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004119 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004120 }
4121 break;
4122
4123 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004124 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004125 int64_t nMantissa;
4126 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004127 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4128 if(uErr) {
4129 return uErr;
4130 }
4131 return ExponentiateNN(nMantissa,
4132 pItem->val.expAndMantissa.nExponent,
4133 pnValue,
4134 Exponentitate10);
4135 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004136 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004137 }
4138 break;
4139
4140 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004141 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004142 int64_t nMantissa;
4143 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004144 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4145 if(uErr) {
4146 return uErr;
4147 }
4148 return ExponentiateNN(nMantissa,
4149 pItem->val.expAndMantissa.nExponent,
4150 pnValue,
4151 Exponentitate2);
4152 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004153 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004154 }
4155 break;
4156
4157 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004158 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004159 int64_t nMantissa;
4160 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004161 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4162 if(uErr) {
4163 return uErr;
4164 }
4165 return ExponentiateNN(nMantissa,
4166 pItem->val.expAndMantissa.nExponent,
4167 pnValue,
4168 Exponentitate2);
4169 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004170 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004171 }
4172 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004173#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4174
Laurence Lundbladee6430642020-03-14 21:15:44 -07004175
Laurence Lundbladec4537442020-04-14 18:53:22 -07004176 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004177 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004178}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004179
4180
Laurence Lundbladec4537442020-04-14 18:53:22 -07004181/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004182 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004183 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004184void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004185{
4186 QCBORItem Item;
4187
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004188 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004189
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004190 if(pMe->uLastError == QCBOR_SUCCESS) {
4191 // The above conversion succeeded
4192 return;
4193 }
4194
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004195 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004196 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004197 return;
4198 }
4199
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004200 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004201}
4202
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004203
4204/*
4205Public function, see header qcbor/qcbor_decode.h file
4206*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004207void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4208 int64_t nLabel,
4209 uint32_t uConvertTypes,
4210 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004211{
4212 QCBORItem Item;
4213
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004214 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004215
4216 if(pMe->uLastError == QCBOR_SUCCESS) {
4217 // The above conversion succeeded
4218 return;
4219 }
4220
4221 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4222 // The above conversion failed in a way that code below can't correct
4223 return;
4224 }
4225
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004226 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004227}
4228
4229
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004230/*
4231Public function, see header qcbor/qcbor_decode.h file
4232*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004233void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4234 const char *szLabel,
4235 uint32_t uConvertTypes,
4236 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004237{
4238 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004239 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004240
4241 if(pMe->uLastError == QCBOR_SUCCESS) {
4242 // The above conversion succeeded
4243 return;
4244 }
4245
4246 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4247 // The above conversion failed in a way that code below can't correct
4248 return;
4249 }
4250
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004251 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004252}
4253
4254
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004255static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004256{
4257 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004258 case QCBOR_TYPE_DOUBLE:
4259 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004260#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004261 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004262 // Can't use llround here because it will not convert values
4263 // greater than INT64_MAX and less than UINT64_MAX that
4264 // need to be converted so it is more complicated.
4265 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4266 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4267 if(isnan(pItem->val.dfnum)) {
4268 return QCBOR_ERR_FLOAT_EXCEPTION;
4269 } else if(pItem->val.dfnum < 0) {
4270 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4271 } else {
4272 double dRounded = round(pItem->val.dfnum);
4273 // See discussion in DecodeDateEpoch() for
4274 // explanation of - 0x7ff
4275 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4276 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4277 }
4278 *puValue = (uint64_t)dRounded;
4279 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004280 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004281 if(isnan(pItem->val.fnum)) {
4282 return QCBOR_ERR_FLOAT_EXCEPTION;
4283 } else if(pItem->val.fnum < 0) {
4284 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4285 } else {
4286 float fRounded = roundf(pItem->val.fnum);
4287 // See discussion in DecodeDateEpoch() for
4288 // explanation of - 0x7ff
4289 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4290 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4291 }
4292 *puValue = (uint64_t)fRounded;
4293 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004294 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004295 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4296 // round() and roundf() shouldn't result in exceptions here, but
4297 // catch them to be robust and thorough. Don't try to
4298 // distinguish between the various exceptions because it seems
4299 // they vary by CPU, compiler and OS.
4300 return QCBOR_ERR_FLOAT_EXCEPTION;
4301 }
4302
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004303 } else {
4304 return QCBOR_ERR_UNEXPECTED_TYPE;
4305 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004306#else
4307 return QCBOR_ERR_HW_FLOAT_DISABLED;
4308#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004309 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004310
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004311 case QCBOR_TYPE_INT64:
4312 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4313 if(pItem->val.int64 >= 0) {
4314 *puValue = (uint64_t)pItem->val.int64;
4315 } else {
4316 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4317 }
4318 } else {
4319 return QCBOR_ERR_UNEXPECTED_TYPE;
4320 }
4321 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004322
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004323 case QCBOR_TYPE_UINT64:
4324 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4325 *puValue = pItem->val.uint64;
4326 } else {
4327 return QCBOR_ERR_UNEXPECTED_TYPE;
4328 }
4329 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004330
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004331 default:
4332 return QCBOR_ERR_UNEXPECTED_TYPE;
4333 }
4334
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004335 return QCBOR_SUCCESS;
4336}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004337
4338
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004339void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004340 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004341 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004342 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004343{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004344 if(pMe->uLastError != QCBOR_SUCCESS) {
4345 return;
4346 }
4347
Laurence Lundbladec4537442020-04-14 18:53:22 -07004348 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004349
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004350 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4351 if(uError) {
4352 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004353 return;
4354 }
4355
Laurence Lundbladea826c502020-05-10 21:07:00 -07004356 if(pItem) {
4357 *pItem = Item;
4358 }
4359
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004360 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004361}
4362
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004363
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004364void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004365 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004366 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004367 uint64_t *puValue,
4368 QCBORItem *pItem)
4369{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004370 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004371 if(pMe->uLastError != QCBOR_SUCCESS) {
4372 return;
4373 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004374
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004375 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004376}
4377
4378
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004379void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004380 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004381 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004382 uint64_t *puValue,
4383 QCBORItem *pItem)
4384{
4385 if(pMe->uLastError != QCBOR_SUCCESS) {
4386 return;
4387 }
4388
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004389 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004390 if(pMe->uLastError != QCBOR_SUCCESS) {
4391 return;
4392 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004393
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004394 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004395}
4396
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004397
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004398/*
4399 Public function, see header qcbor/qcbor_decode.h file
4400*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004401static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004402{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004403 switch(pItem->uDataType) {
4404
4405 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004406 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004407 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4408 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004409 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004410 }
4411 break;
4412
4413 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004414 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004415 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4416 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004417 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004418 }
4419 break;
4420
4421#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4422
4423 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004424 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004425 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004426 pItem->val.expAndMantissa.nExponent,
4427 puValue,
4428 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004429 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004430 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004431 }
4432 break;
4433
4434 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004435 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004436 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4437 pItem->val.expAndMantissa.nExponent,
4438 puValue,
4439 Exponentitate2);
4440 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004441 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004442 }
4443 break;
4444
4445 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004446 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004447 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004448 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004449 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004450 if(uErr != QCBOR_SUCCESS) {
4451 return uErr;
4452 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004453 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004454 pItem->val.expAndMantissa.nExponent,
4455 puValue,
4456 Exponentitate10);
4457 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004458 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004459 }
4460 break;
4461
4462 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004463 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004464 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4465 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004466 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004467 }
4468 break;
4469
4470 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004471 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004472 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004473 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004474 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004475 if(uErr != QCBOR_SUCCESS) {
4476 return uErr;
4477 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004478 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004479 pItem->val.expAndMantissa.nExponent,
4480 puValue,
4481 Exponentitate2);
4482 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004483 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004484 }
4485 break;
4486
4487 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004488 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004489 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4490 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004491 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004492 }
4493 break;
4494#endif
4495 default:
4496 return QCBOR_ERR_UNEXPECTED_TYPE;
4497 }
4498}
4499
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004500
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004501/*
4502 Public function, see header qcbor/qcbor_decode.h file
4503*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004504void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004505{
4506 QCBORItem Item;
4507
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004508 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004509
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004510 if(pMe->uLastError == QCBOR_SUCCESS) {
4511 // The above conversion succeeded
4512 return;
4513 }
4514
4515 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4516 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004517 return;
4518 }
4519
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004520 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004521}
4522
Laurence Lundbladec4537442020-04-14 18:53:22 -07004523
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004524/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004525 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004526*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004527void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004528 int64_t nLabel,
4529 uint32_t uConvertTypes,
4530 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004531{
4532 QCBORItem Item;
4533
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004534 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004535
4536 if(pMe->uLastError == QCBOR_SUCCESS) {
4537 // The above conversion succeeded
4538 return;
4539 }
4540
4541 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4542 // The above conversion failed in a way that code below can't correct
4543 return;
4544 }
4545
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004546 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004547}
4548
4549
4550/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004551 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004552*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004553void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004554 const char *szLabel,
4555 uint32_t uConvertTypes,
4556 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004557{
4558 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004559 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004560
4561 if(pMe->uLastError == QCBOR_SUCCESS) {
4562 // The above conversion succeeded
4563 return;
4564 }
4565
4566 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4567 // The above conversion failed in a way that code below can't correct
4568 return;
4569 }
4570
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004571 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004572}
4573
4574
Laurence Lundblade9b334962020-08-27 10:55:53 -07004575static QCBORError ConvertDouble(const QCBORItem *pItem,
4576 uint32_t uConvertTypes,
4577 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004578{
4579 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004580 case QCBOR_TYPE_FLOAT:
4581#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4582 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4583 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004584 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004585 *pdValue = (double)pItem->val.fnum;
4586 } else {
4587 return QCBOR_ERR_UNEXPECTED_TYPE;
4588 }
4589 }
4590#else
4591 return QCBOR_ERR_HW_FLOAT_DISABLED;
4592#endif
4593 break;
4594
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004595 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004596 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4597 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004598 *pdValue = pItem->val.dfnum;
4599 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004600 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004601 }
4602 }
4603 break;
4604
4605 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004606#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004607 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004608 // A simple cast seems to do the job with no worry of exceptions.
4609 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004610 *pdValue = (double)pItem->val.int64;
4611
4612 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004613 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004614 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004615#else
4616 return QCBOR_ERR_HW_FLOAT_DISABLED;
4617#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004618 break;
4619
4620 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004621#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004622 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004623 // A simple cast seems to do the job with no worry of exceptions.
4624 // There will be precision loss for some values.
4625 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004626 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004627 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004628 }
4629 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004630#else
4631 return QCBOR_ERR_HW_FLOAT_DISABLED;
4632#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004633
4634 default:
4635 return QCBOR_ERR_UNEXPECTED_TYPE;
4636 }
4637
4638 return QCBOR_SUCCESS;
4639}
4640
4641
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004642void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004643 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004644 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004645 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004646{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004647 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004648 return;
4649 }
4650
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004651 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004652
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004653 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004654 if(uError) {
4655 pMe->uLastError = (uint8_t)uError;
4656 return;
4657 }
4658
4659 if(pItem) {
4660 *pItem = Item;
4661 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004662
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004663 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004664}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004665
Laurence Lundbladec4537442020-04-14 18:53:22 -07004666
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004667void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4668 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004669 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004670 double *pdValue,
4671 QCBORItem *pItem)
4672{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004673 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004674 if(pMe->uLastError != QCBOR_SUCCESS) {
4675 return;
4676 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004677
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004678 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004679}
4680
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004681
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004682void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4683 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004684 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004685 double *pdValue,
4686 QCBORItem *pItem)
4687{
4688 if(pMe->uLastError != QCBOR_SUCCESS) {
4689 return;
4690 }
4691
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004692 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004693 if(pMe->uLastError != QCBOR_SUCCESS) {
4694 return;
4695 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004696
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004697 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004698}
4699
4700
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004701#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004702static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4703{
4704 double dResult;
4705
4706 dResult = 0.0;
4707 const uint8_t *pByte = BigNum.ptr;
4708 size_t uLen = BigNum.len;
4709 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004710 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004711 while(uLen--) {
4712 dResult = (dResult * 256.0) + (double)*pByte++;
4713 }
4714
4715 return dResult;
4716}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004717#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4718
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004719
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004720static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004721{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004722#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004723 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004724 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4725
4726 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004727 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004728
4729#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004730 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004731 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004732 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004733 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4734 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4735 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004736 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004737 }
4738 break;
4739
4740 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004741 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004742 // Underflow gives 0, overflow gives infinity
4743 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4744 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004745 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004746 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004747 }
4748 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004749#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004750
4751 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004752 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004753 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4754 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004755 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004756 }
4757 break;
4758
4759 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004760 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004761 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004762 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004763 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004764 }
4765 break;
4766
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004767#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004768 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004769 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004770 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4771 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4772 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004773 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004774 }
4775 break;
4776
4777 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004778 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004779 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4780 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4781 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004782 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004783 }
4784 break;
4785
4786 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004787 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004788 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4789 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4790 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004791 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004792 }
4793 break;
4794
4795 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004796 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004797 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004798 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4799 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004800 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004801 }
4802 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004803#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4804
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004805 default:
4806 return QCBOR_ERR_UNEXPECTED_TYPE;
4807 }
4808
4809 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004810
4811#else
4812 (void)pItem;
4813 (void)uConvertTypes;
4814 (void)pdValue;
4815 return QCBOR_ERR_HW_FLOAT_DISABLED;
4816#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4817
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004818}
4819
4820
4821/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004822 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004823*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004824void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4825 uint32_t uConvertTypes,
4826 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004827{
4828
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004829 QCBORItem Item;
4830
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004831 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004832
4833 if(pMe->uLastError == QCBOR_SUCCESS) {
4834 // The above conversion succeeded
4835 return;
4836 }
4837
4838 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4839 // The above conversion failed in a way that code below can't correct
4840 return;
4841 }
4842
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004843 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004844}
4845
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004846
4847/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004848 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004849*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004850void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4851 int64_t nLabel,
4852 uint32_t uConvertTypes,
4853 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004854{
4855 QCBORItem Item;
4856
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004857 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004858
4859 if(pMe->uLastError == QCBOR_SUCCESS) {
4860 // The above conversion succeeded
4861 return;
4862 }
4863
4864 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4865 // The above conversion failed in a way that code below can't correct
4866 return;
4867 }
4868
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004869 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004870}
4871
4872
4873/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004874 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004875*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004876void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4877 const char *szLabel,
4878 uint32_t uConvertTypes,
4879 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004880{
4881 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004882 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004883
4884 if(pMe->uLastError == QCBOR_SUCCESS) {
4885 // The above conversion succeeded
4886 return;
4887 }
4888
4889 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4890 // The above conversion failed in a way that code below can't correct
4891 return;
4892 }
4893
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004894 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004895}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004896
4897
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004898
4899
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004900#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004901static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4902{
4903 while((uInt & 0xff00000000000000UL) == 0) {
4904 uInt = uInt << 8;
4905 };
4906
4907 UsefulOutBuf UOB;
4908
4909 UsefulOutBuf_Init(&UOB, Buffer);
4910
4911 while(uInt) {
4912 const uint64_t xx = uInt & 0xff00000000000000UL;
4913 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4914 uInt = uInt << 8;
4915 (void)xx;
4916 }
4917
4918 return UsefulOutBuf_OutUBuf(&UOB);
4919}
4920
4921
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004922static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4923 TagSpecification TagSpec,
4924 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004925{
4926 QCBORError uErr;
4927 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004928 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004929 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004930 if(uErr != QCBOR_SUCCESS) {
4931 goto Done;
4932 }
4933
4934 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4935 break; // Successful exit. Moving on to finish decoding.
4936 }
4937
4938 // The item is an array, which means an undecoded
4939 // mantissa and exponent, so decode it. It will then
4940 // have a different type and exit the loop if.
4941 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4942 if(uErr != QCBOR_SUCCESS) {
4943 goto Done;
4944 }
4945
4946 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07004947 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004948 }
4949Done:
4950 return uErr;
4951}
4952
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004953
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004954static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004955 TagSpecification TagSpec,
4956 QCBORItem *pItem,
4957 int64_t *pnMantissa,
4958 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004959{
4960 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004961
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004962 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004963 if(uErr != QCBOR_SUCCESS) {
4964 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004965 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004966
Laurence Lundblade9b334962020-08-27 10:55:53 -07004967 switch (pItem->uDataType) {
4968
4969 case QCBOR_TYPE_DECIMAL_FRACTION:
4970 case QCBOR_TYPE_BIGFLOAT:
4971 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4972 *pnExponent = pItem->val.expAndMantissa.nExponent;
4973 break;
4974
4975 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4976 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4977 *pnExponent = pItem->val.expAndMantissa.nExponent;
4978 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4979 break;
4980
4981 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4982 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4983 *pnExponent = pItem->val.expAndMantissa.nExponent;
4984 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4985 break;
4986
4987 default:
4988 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
4989 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004990
4991 Done:
4992 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004993}
4994
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004995
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004996static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004997 TagSpecification TagSpec,
4998 QCBORItem *pItem,
4999 UsefulBuf BufferForMantissa,
5000 UsefulBufC *pMantissa,
5001 bool *pbIsNegative,
5002 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005003{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005004 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005005
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005006 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005007 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005008 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005009 }
5010
5011 uint64_t uMantissa;
5012
5013 switch (pItem->uDataType) {
5014
5015 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005016 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005017 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5018 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5019 *pbIsNegative = false;
5020 } else {
5021 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5022 *pbIsNegative = true;
5023 }
5024 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5025 *pnExponent = pItem->val.expAndMantissa.nExponent;
5026 break;
5027
5028 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005029 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005030 *pnExponent = pItem->val.expAndMantissa.nExponent;
5031 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5032 *pbIsNegative = false;
5033 break;
5034
5035 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005036 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005037 *pnExponent = pItem->val.expAndMantissa.nExponent;
5038 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5039 *pbIsNegative = true;
5040 break;
5041
5042 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005043 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005044 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005045
5046Done:
5047 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005048}
5049
5050
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005051/*
5052 Public function, see header qcbor/qcbor_decode.h file
5053*/
5054void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5055 uint8_t uTagRequirement,
5056 int64_t *pnMantissa,
5057 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005058{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005059 if(pMe->uLastError != QCBOR_SUCCESS) {
5060 return;
5061 }
5062
5063 QCBORItem Item;
5064 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5065 if(uError) {
5066 pMe->uLastError = (uint8_t)uError;
5067 return;
5068 }
5069
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005070 const TagSpecification TagSpec =
5071 {
5072 uTagRequirement,
5073 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5074 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5075 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005076
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005077 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005078}
5079
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005080
5081/*
5082 Public function, see header qcbor/qcbor_decode.h file
5083*/
5084void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005085 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005086 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005087 int64_t *pnMantissa,
5088 int64_t *pnExponent)
5089{
5090 if(pMe->uLastError != QCBOR_SUCCESS) {
5091 return;
5092 }
5093
5094 QCBORItem Item;
5095 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5096
5097 const TagSpecification TagSpec =
5098 {
5099 uTagRequirement,
5100 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5101 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5102 };
5103
5104 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5105}
5106
5107
5108/*
5109 Public function, see header qcbor/qcbor_decode.h file
5110*/
5111void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005112 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005113 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005114 int64_t *pnMantissa,
5115 int64_t *pnExponent)
5116{
5117 if(pMe->uLastError != QCBOR_SUCCESS) {
5118 return;
5119 }
5120
5121 QCBORItem Item;
5122 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5123
5124 const TagSpecification TagSpec =
5125 {
5126 uTagRequirement,
5127 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5128 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5129 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005130
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005131 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5132}
5133
5134
5135/*
5136 Public function, see header qcbor/qcbor_decode.h file
5137*/
5138void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5139 uint8_t uTagRequirement,
5140 UsefulBuf MantissaBuffer,
5141 UsefulBufC *pMantissa,
5142 bool *pbMantissaIsNegative,
5143 int64_t *pnExponent)
5144{
5145 if(pMe->uLastError != QCBOR_SUCCESS) {
5146 return;
5147 }
5148
5149 QCBORItem Item;
5150 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5151 if(uError) {
5152 pMe->uLastError = (uint8_t)uError;
5153 return;
5154 }
5155
5156 const TagSpecification TagSpec =
5157 {
5158 uTagRequirement,
5159 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5160 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5161 };
5162
5163 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
5164}
5165
5166
5167/*
5168 Public function, see header qcbor/qcbor_decode.h file
5169*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005170void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005171 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005172 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005173 UsefulBuf BufferForMantissa,
5174 UsefulBufC *pMantissa,
5175 bool *pbIsNegative,
5176 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005177{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005178 if(pMe->uLastError != QCBOR_SUCCESS) {
5179 return;
5180 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005181
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005182 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005183 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005184 if(pMe->uLastError != QCBOR_SUCCESS) {
5185 return;
5186 }
5187
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005188 const TagSpecification TagSpec =
5189 {
5190 uTagRequirement,
5191 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5192 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5193 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005194
5195 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005196}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005197
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005198
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005199/*
5200 Public function, see header qcbor/qcbor_decode.h file
5201*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005202void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005203 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005204 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005205 UsefulBuf BufferForMantissa,
5206 UsefulBufC *pMantissa,
5207 bool *pbIsNegative,
5208 int64_t *pnExponent)
5209{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005210 if(pMe->uLastError != QCBOR_SUCCESS) {
5211 return;
5212 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005213
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005214 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005215 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5216 if(pMe->uLastError != QCBOR_SUCCESS) {
5217 return;
5218 }
5219
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005220 const TagSpecification TagSpec =
5221 {
5222 uTagRequirement,
5223 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5224 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5225 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005226
5227 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5228}
5229
5230
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005231/*
5232 Public function, see header qcbor/qcbor_decode.h file
5233*/
5234void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5235 uint8_t uTagRequirement,
5236 int64_t *pnMantissa,
5237 int64_t *pnExponent)
5238{
5239 if(pMe->uLastError != QCBOR_SUCCESS) {
5240 return;
5241 }
5242
5243 QCBORItem Item;
5244 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5245 if(uError) {
5246 pMe->uLastError = (uint8_t)uError;
5247 return;
5248 }
5249 const TagSpecification TagSpec =
5250 {
5251 uTagRequirement,
5252 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5253 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5254 };
5255
5256 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5257}
5258
5259
5260/*
5261 Public function, see header qcbor/qcbor_decode.h file
5262*/
5263void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005264 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005265 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005266 int64_t *pnMantissa,
5267 int64_t *pnExponent)
5268{
5269 if(pMe->uLastError != QCBOR_SUCCESS) {
5270 return;
5271 }
5272
5273 QCBORItem Item;
5274 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5275 if(pMe->uLastError != QCBOR_SUCCESS) {
5276 return;
5277 }
5278
5279 const TagSpecification TagSpec =
5280 {
5281 uTagRequirement,
5282 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5283 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5284 };
5285
5286 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5287}
5288
5289
5290/*
5291 Public function, see header qcbor/qcbor_decode.h file
5292*/
5293void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005294 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005295 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005296 int64_t *pnMantissa,
5297 int64_t *pnExponent)
5298{
5299 if(pMe->uLastError != QCBOR_SUCCESS) {
5300 return;
5301 }
5302
5303 QCBORItem Item;
5304 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5305 if(pMe->uLastError != QCBOR_SUCCESS) {
5306 return;
5307 }
5308
5309 const TagSpecification TagSpec =
5310 {
5311 uTagRequirement,
5312 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5313 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5314 };
5315
5316 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5317}
5318
5319
5320/*
5321 Public function, see header qcbor/qcbor_decode.h file
5322*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005323void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5324 uint8_t uTagRequirement,
5325 UsefulBuf MantissaBuffer,
5326 UsefulBufC *pMantissa,
5327 bool *pbMantissaIsNegative,
5328 int64_t *pnExponent)
5329{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005330 if(pMe->uLastError != QCBOR_SUCCESS) {
5331 return;
5332 }
5333
5334 QCBORItem Item;
5335 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5336 if(uError) {
5337 pMe->uLastError = (uint8_t)uError;
5338 return;
5339 }
5340
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005341 const TagSpecification TagSpec =
5342 {
5343 uTagRequirement,
5344 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5345 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5346 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005347
5348 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005349}
5350
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005351
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005352/*
5353 Public function, see header qcbor/qcbor_decode.h file
5354*/
5355void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005356 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005357 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005358 UsefulBuf BufferForMantissa,
5359 UsefulBufC *pMantissa,
5360 bool *pbIsNegative,
5361 int64_t *pnExponent)
5362{
5363 if(pMe->uLastError != QCBOR_SUCCESS) {
5364 return;
5365 }
5366
5367 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005368 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5369 if(pMe->uLastError != QCBOR_SUCCESS) {
5370 return;
5371 }
5372
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005373 const TagSpecification TagSpec =
5374 {
5375 uTagRequirement,
5376 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5377 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5378 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005379
5380 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5381}
5382
5383
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005384/*
5385 Public function, see header qcbor/qcbor_decode.h file
5386*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005387void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005388 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005389 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005390 UsefulBuf BufferForMantissa,
5391 UsefulBufC *pMantissa,
5392 bool *pbIsNegative,
5393 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005394{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005395 if(pMe->uLastError != QCBOR_SUCCESS) {
5396 return;
5397 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005398
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005399 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005400 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5401 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005402 return;
5403 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005404
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005405 const TagSpecification TagSpec =
5406 {
5407 uTagRequirement,
5408 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5409 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5410 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005411
5412 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005413}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005414
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005415#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */