blob: d9e6912b6ffe79fb2134d6c76b9f72f1593291bb [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
39#include <math.h> // For isnan(). TODO: list
40#endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070041
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070042
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053043/*
44 This casts away the const-ness of a pointer, usually so it can be
45 freed or realloced.
46 */
47#define UNCONST_POINTER(ptr) ((void *)(ptr))
48
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070049
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070050
Laurence Lundblade02625d42020-06-25 14:41:41 -070051inline static bool
52// TODO: add more tests for QCBOR_TYPE_MAP_AS_ARRAY mode in qcbor_decode_tests.c
53QCBORItem_IsMapOrArray(const QCBORItem *pMe)
54{
55 const uint8_t uDataType = pMe->uDataType;
56 return uDataType == QCBOR_TYPE_MAP ||
57 uDataType == QCBOR_TYPE_ARRAY ||
58 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
59}
60
61inline static bool
62QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
63{
64 if(!QCBORItem_IsMapOrArray(pMe)){
65 return false;
66 }
67
68 if(pMe->val.uCount != 0) {
69 return false;
70 }
71 return true;
72}
73
74inline static bool
75QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
76{
77 if(!QCBORItem_IsMapOrArray(pMe)){
78 return false;
79 }
80
81 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
82 return false;
83 }
84 return true;
85}
86
87
Laurence Lundbladeee851742020-01-08 08:37:05 -080088/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070089 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080090 ===========================================================================*/
91
Laurence Lundblade9c905e82020-04-25 11:31:38 -070092/*
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070093 See commecnts about and typedef of QCBORDecodeNesting in qcbor_private.h, the data structure
94 all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -070095
Laurence Lundblade9c905e82020-04-25 11:31:38 -070096
Laurence Lundblade9c905e82020-04-25 11:31:38 -070097
Laurence Lundblade9c905e82020-04-25 11:31:38 -070098 */
99
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700100
101inline static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700102DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700103{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700104 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700105 /*
106 Limit in DecodeNesting_Descend against more than
107 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
108 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700109 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700110}
111
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700112
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700113inline static uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700114DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700115{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700116 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700117 /*
118 Limit in DecodeNesting_Descend against more than
119 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
120 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700121 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700122}
123
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700124
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700125static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700126DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700127{
128 return pNesting->pCurrentBounded->u.ma.uStartOffset;
129}
130
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700131
Laurence Lundblade085d7952020-07-24 10:26:30 -0700132static inline bool
133DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
134{
135 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
136 return true;
137 } else {
138 return false;
139 }
140}
141
142
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700143inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700144DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700145{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700146 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700147 return true;
148 } else {
149 return false;
150 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700151}
152
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700153
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700154inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700155DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700156{
157 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700158 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700159 return false;
160 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700161 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700162 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700163 return false;
164 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700165 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700166 return true;
167}
168
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700169
Laurence Lundblade642282a2020-06-23 12:00:33 -0700170inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700171DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700172{
173 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700174 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700175 return true;
176 }
177 return false;
178}
179
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700180
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700181inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700182{
183 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
184 return true;
185 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700186 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700187 return true;
188 }
189 return false;
190}
191
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700192
Laurence Lundblade085d7952020-07-24 10:26:30 -0700193inline static void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700194{
195 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700196 /*
197 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
198 larger than DecodeNesting_EnterBoundedMode which keeps it less than
199 uin32_t so the cast is safe.
200 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700201 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700202
203 if(bIsEmpty) {
204 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
205 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700206}
207
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700208
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700209inline static void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700210{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700211 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700212}
213
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700214
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700215inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700216DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700217{
218 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700219 // No bounded map or array or... set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700220 return false;
221 }
222 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700223 // Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700224 return false;
225 }
226 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700227 // Not at a bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700228 return false;
229 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700230 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700231 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700232 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700233 return false;
234 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700235 // All checks passed, got to the end of a map/array
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700236 return true;
237}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700238
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700239
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700240inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700241DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700242{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700243 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700244 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
245 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700246 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700247 return false;
248 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700249}
250
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700251
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700252inline static bool
253DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700254{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700255 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
256 return true;
257 } else {
258 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700259 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700260}
261
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700262
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700263inline static bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700264DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700265{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700266 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700267 return false;
268 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700269
270 if(pNesting->pCurrentBounded->uLevelType != uType) {
271 return false;
272 }
273
274 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700275}
276
Laurence Lundblade02625d42020-06-25 14:41:41 -0700277
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700278inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700279DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700280{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700281 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700282 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700283}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700284
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700285
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700286inline static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700287DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
288{
289 // Only call on a defnite length array / map
290 pNesting->pCurrent->u.ma.uCountCursor++;
291}
292
293
294inline static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700295DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
296{
297 pNesting->pCurrent--;
298}
299
Laurence Lundblade02625d42020-06-25 14:41:41 -0700300
301static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700302DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700303{
304 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700305 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700306 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
307 }
308
309 // The actual descend
310 pNesting->pCurrent++;
311
312 pNesting->pCurrent->uLevelType = uType;
313
314 return QCBOR_SUCCESS;
315}
316
317
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700318inline static QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700319DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700320{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700321 /*
322 Should only be called on map/array.
323
324 Have descended into this before this is called. The job here is
325 just to mark it in bounded mode.
326 */
Laurence Lundblade287b25c2020-08-06 13:48:42 -0700327 if(uOffset >= QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700328 return QCBOR_ERR_BUFFER_TOO_LARGE;
329 }
330
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700331 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700332
333 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700334
335 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700336}
337
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700338
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700339inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700340DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700341 uint8_t uQCBORType,
342 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700343{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700344 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700345
346 if(uCount == 0) {
347 // Nothing to do for empty definite lenth arrays. They are just are
348 // effectively the same as an item that is not a map or array
349 goto Done;
350 // Empty indefinite length maps and arrays are handled elsewhere
351 }
352
353 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700354 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
355 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
356 uError = QCBOR_ERR_ARRAY_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700357 goto Done;
358 }
359
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700360 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700361 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700362 goto Done;
363 }
364
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700365 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700366 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
367 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700368
369 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700370
371Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700372 return uError;;
373}
374
375
376static inline void
377DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
378{
379 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
380}
381
382
383static inline void
384DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
385{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700386 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700387 pNesting->pCurrentBounded--;
388 if(DecodeNesting_IsCurrentBounded(pNesting)) {
389 break;
390 }
391 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700392}
393
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700394static inline void
395DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
396{
397 pNesting->pCurrent = pNesting->pCurrentBounded;
398}
399
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700400
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700401inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700402DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700403 uint32_t uEndOffset,
404 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700405{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700406 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700407
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700408 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700409 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700410 goto Done;
411 }
412
Laurence Lundblade02625d42020-06-25 14:41:41 -0700413 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700414 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
415 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700416
Laurence Lundblade02625d42020-06-25 14:41:41 -0700417 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700418 pNesting->pCurrentBounded = pNesting->pCurrent;
419
420Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700421 return uError;;
422}
423
Laurence Lundbladed0304932020-06-27 10:59:38 -0700424
425static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700426DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700427{
428 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700429}
430
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700431
Laurence Lundbladeee851742020-01-08 08:37:05 -0800432inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700433DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700434{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700435 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700436 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
437 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700438}
439
440
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700441inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700442DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700443{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700444 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700445 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700446 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700447}
448
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700449
Laurence Lundblade02625d42020-06-25 14:41:41 -0700450static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700451DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700452{
453 *pNesting = *pSave;
454}
455
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700456
Laurence Lundblade02625d42020-06-25 14:41:41 -0700457static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700458DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700459{
460 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
461}
462
463
Laurence Lundblade02625d42020-06-25 14:41:41 -0700464static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700465DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700466{
467 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
468}
469
470
Laurence Lundblade02625d42020-06-25 14:41:41 -0700471#include <stdio.h>
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700472
473const char *TypeStr(uint8_t type)
474{
475 switch(type) {
476 case QCBOR_TYPE_MAP: return " map";
477 case QCBOR_TYPE_ARRAY: return "array";
478 case QCBOR_TYPE_BYTE_STRING: return " bstr";
479 default: return " --- ";
480 }
481}
482
483static char buf[20]; // Not thread safe, but that is OK
484const char *CountString(uint16_t uCount, uint16_t uTotal)
485{
486 if(uTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
487 strcpy(buf, "indefinite");
488 } else {
489 sprintf(buf, "%d/%d", uCount, uTotal);
490 }
491 return buf;
492}
493
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700494
Laurence Lundblade02625d42020-06-25 14:41:41 -0700495void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700496{
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700497#if 0
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700498 printf("---%s--%d/%d--\narrow is current bounded level\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700499 szName,
500 (uint32_t)pBuf->cursor,
501 (uint32_t)pBuf->UB.len);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700502
503 printf("Level Type Count Offsets \n");
Laurence Lundblade02625d42020-06-25 14:41:41 -0700504 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700505 if(&(pNesting->pLevels[i]) > pNesting->pCurrent) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700506 break;
507 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700508
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700509 printf("%2s %2d %s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700510 pNesting->pCurrentBounded == &(pNesting->pLevels[i]) ? "->": " ",
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700511 i,
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700512 TypeStr(pNesting->pLevels[i].uLevelType));
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700513
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700514 if(pNesting->pLevels[i].uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700515 printf(" %5d %5d",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700516 pNesting->pLevels[i].u.bs.uEndOfBstr,
517 pNesting->pLevels[i].u.bs.uPreviousEndOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700518
519 } else {
520 printf("%10.10s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700521 CountString(pNesting->pLevels[i].u.ma.uCountCursor,
522 pNesting->pLevels[i].u.ma.uCountTotal));
523 if(pNesting->pLevels[i].u.ma.uStartOffset != UINT32_MAX) {
524 printf("Bounded start: %u",pNesting->pLevels[i].u.ma.uStartOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700525 }
526 }
527
528 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700529 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700530 printf("\n");
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700531#endif
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700532}
533
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700534
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700535
Laurence Lundbladeee851742020-01-08 08:37:05 -0800536/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800537 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
538
539 The following four functions are pretty wrappers for invocation of
540 the string allocator supplied by the caller.
541
Laurence Lundbladeee851742020-01-08 08:37:05 -0800542 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800543
Laurence Lundbladeee851742020-01-08 08:37:05 -0800544static inline void
545StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800546{
547 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
548}
549
Laurence Lundbladeee851742020-01-08 08:37:05 -0800550// StringAllocator_Reallocate called with pMem NULL is
551// equal to StringAllocator_Allocate()
552static inline UsefulBuf
553StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
554 void *pMem,
555 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800556{
557 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
558}
559
Laurence Lundbladeee851742020-01-08 08:37:05 -0800560static inline UsefulBuf
561StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800562{
563 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
564}
565
Laurence Lundbladeee851742020-01-08 08:37:05 -0800566static inline void
567StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800568{
569 if(pMe->pfAllocator) {
570 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
571 }
572}
573
574
575
Laurence Lundbladeee851742020-01-08 08:37:05 -0800576/*===========================================================================
577 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700578
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800579 See qcbor/qcbor_decode.h for definition of the object
580 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800581 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700582/*
583 Public function, see header file
584 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800585void QCBORDecode_Init(QCBORDecodeContext *me,
586 UsefulBufC EncodedCBOR,
587 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700588{
589 memset(me, 0, sizeof(QCBORDecodeContext));
590 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800591 // Don't bother with error check on decode mode. If a bad value is
592 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700593 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700594 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700595 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700596 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700597 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700598}
599
600
601/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700602 Public function, see header file
603 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800604void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
605 QCBORStringAllocate pfAllocateFunction,
606 void *pAllocateContext,
607 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700608{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800609 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
610 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
611 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700612}
613
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800614
615/*
616 Public function, see header file
617 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700618void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800619 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700620{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700621 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700622 (void)pMe;
623 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700624}
625
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700626
627/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800628 This decodes the fundamental part of a CBOR data item, the type and
629 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800630
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700631 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800632
Laurence Lundbladeee851742020-01-08 08:37:05 -0800633 This does the network->host byte order conversion. The conversion
634 here also results in the conversion for floats in addition to that
635 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800636
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700637 This returns:
638 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800639
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800640 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800641 tags and floats and length for strings and arrays
642
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800643 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800644 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800645
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800646 The int type is preferred to uint8_t for some variables as this
647 avoids integer promotions, can reduce code size and makes
648 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700649 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800650inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
651 int *pnMajorType,
652 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800653 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700654{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700655 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800656
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700657 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800658 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800659
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700660 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800661 const int nTmpMajorType = nInitialByte >> 5;
662 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800663
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800664 // Where the number or argument accumulates
665 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800666
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800667 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700668 // Need to get 1,2,4 or 8 additional argument bytes. Map
669 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800670 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800671
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800672 // Loop getting all the bytes in the argument
673 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800674 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800675 // This shift and add gives the endian conversion
676 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
677 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800678 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800679 // The reserved and thus-far unused additional info values
680 nReturn = QCBOR_ERR_UNSUPPORTED;
681 goto Done;
682 } else {
683 // Less than 24, additional info is argument or 31, an indefinite length
684 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800685 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700686 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800687
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700688 if(UsefulInputBuf_GetError(pUInBuf)) {
689 nReturn = QCBOR_ERR_HIT_END;
690 goto Done;
691 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800692
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700693 // All successful if we got here.
694 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800695 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800696 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800697 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800698
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700699Done:
700 return nReturn;
701}
702
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800703
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700704/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800705 CBOR doesn't explicitly specify two's compliment for integers but all
706 CPUs use it these days and the test vectors in the RFC are so. All
707 integers in the CBOR structure are positive and the major type
708 indicates positive or negative. CBOR can express positive integers
709 up to 2^x - 1 where x is the number of bits and negative integers
710 down to 2^x. Note that negative numbers can be one more away from
711 zero than positive. Stdint, as far as I can tell, uses two's
712 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800713
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700714 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800715 used carefully here, and in particular why it isn't used in the interface.
716 Also see
717 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
718
719 Int is used for values that need less than 16-bits and would be subject
720 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700721 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800722inline static QCBORError
723DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700725 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800726
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700727 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
728 if (uNumber <= INT64_MAX) {
729 pDecodedItem->val.int64 = (int64_t)uNumber;
730 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800731
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732 } else {
733 pDecodedItem->val.uint64 = uNumber;
734 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800735
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700736 }
737 } else {
738 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800739 // CBOR's representation of negative numbers lines up with the
740 // two-compliment representation. A negative integer has one
741 // more in range than a positive integer. INT64_MIN is
742 // equal to (-INT64_MAX) - 1.
743 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700744 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800745
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746 } else {
747 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000748 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700749 nReturn = QCBOR_ERR_INT_OVERFLOW;
750 }
751 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800752
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700753 return nReturn;
754}
755
756// Make sure #define value line up as DecodeSimple counts on this.
757#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
758#error QCBOR_TYPE_FALSE macro value wrong
759#endif
760
761#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
762#error QCBOR_TYPE_TRUE macro value wrong
763#endif
764
765#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
766#error QCBOR_TYPE_NULL macro value wrong
767#endif
768
769#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
770#error QCBOR_TYPE_UNDEF macro value wrong
771#endif
772
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700773#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
774#error QCBOR_TYPE_BREAK macro value wrong
775#endif
776
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700777#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
778#error QCBOR_TYPE_DOUBLE macro value wrong
779#endif
780
781#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
782#error QCBOR_TYPE_FLOAT macro value wrong
783#endif
784
785/*
786 Decode true, false, floats, break...
787 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800788inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800789DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700790{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700791 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800792
Laurence Lundbladeee851742020-01-08 08:37:05 -0800793 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800794 // above make sure uAdditionalInfo values line up with uDataType values.
795 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
796 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800797
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800798 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800799 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
800 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800801
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700802 case HALF_PREC_FLOAT:
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700803#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700804 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700805 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700806 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700807 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
808 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700809#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700810 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700811#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700812 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700813 case SINGLE_PREC_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700814 // Single precision is normally returned as a double
815 // since double is widely supported, there is no loss of
816 // precision, it makes it easy for the caller in
817 // most cases and it can be converted back to single
818 // with no loss of precision
819 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700820 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700821 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700822 {
823 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
824#ifndef QCBOR_DISABLE_FLOAT_HW_USE
825 // In the normal case, use HW to convert float to double.
826 pDecodedItem->val.dfnum = (double)f;
827 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700828#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700829 // Use of float HW is disabled, return as a float.
830 pDecodedItem->val.fnum = f;
831 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
832
833 // IEEE754_FloatToDouble() could be used here to return
834 // as a double, but it adds object code and most likely
835 // anyone disabling FLOAT HW use doesn't care about
836 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700837#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700838 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700839 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700840
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700841 case DOUBLE_PREC_FLOAT:
842 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700843 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700844 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800845
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700846 case CBOR_SIMPLEV_FALSE: // 20
847 case CBOR_SIMPLEV_TRUE: // 21
848 case CBOR_SIMPLEV_NULL: // 22
849 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700850 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700851 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800852
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700853 case CBOR_SIMPLEV_ONEBYTE: // 24
854 if(uNumber <= CBOR_SIMPLE_BREAK) {
855 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700856 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700857 goto Done;
858 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800859 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700860 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800861
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700862 default: // 0-19
863 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800864 /*
865 DecodeTypeAndNumber will make uNumber equal to
866 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
867 safe because the 2, 4 and 8 byte lengths of uNumber are in
868 the double/float cases above
869 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700870 pDecodedItem->val.uSimple = (uint8_t)uNumber;
871 break;
872 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800873
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700874Done:
875 return nReturn;
876}
877
878
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700879/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530880 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700881 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800882inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
883 int nMajorType,
884 uint64_t uStrLen,
885 UsefulInputBuf *pUInBuf,
886 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700887{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700888 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800889
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800890 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
891 // This check makes the casts to size_t below safe.
892
893 // 4 bytes less than the largest sizeof() so this can be tested by
894 // putting a SIZE_MAX length in the CBOR test input (no one will
895 // care the limit on strings is 4 bytes shorter).
896 if(uStrLen > SIZE_MAX-4) {
897 nReturn = QCBOR_ERR_STRING_TOO_LONG;
898 goto Done;
899 }
900
901 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530902 if(UsefulBuf_IsNULLC(Bytes)) {
903 // Failed to get the bytes for this string item
904 nReturn = QCBOR_ERR_HIT_END;
905 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700906 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530907
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800908 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530909 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800910 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530911 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700912 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530913 goto Done;
914 }
915 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800916 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530917 } else {
918 // Normal case with no string allocator
919 pDecodedItem->val.string = Bytes;
920 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800921 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800922 // Cast because ternary operator causes promotion to integer
923 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
924 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800925
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530926Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700927 return nReturn;
928}
929
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700930
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800931
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700932
933
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700934
935
Laurence Lundbladeee851742020-01-08 08:37:05 -0800936// Make sure the constants align as this is assumed by
937// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700938#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
939#error QCBOR_TYPE_ARRAY value not lined up with major type
940#endif
941#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
942#error QCBOR_TYPE_MAP value not lined up with major type
943#endif
944
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700945/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800946 This gets a single data item and decodes it including preceding
947 optional tagging. This does not deal with arrays and maps and nesting
948 except to decode the data item introducing them. Arrays and maps are
949 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800950
Laurence Lundbladeee851742020-01-08 08:37:05 -0800951 Errors detected here include: an array that is too long to decode,
952 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700953 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800954static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
955 QCBORItem *pDecodedItem,
956 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700957{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700958 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800959
Laurence Lundbladeee851742020-01-08 08:37:05 -0800960 /*
961 Get the major type and the number. Number could be length of more
962 bytes or the value depending on the major type nAdditionalInfo is
963 an encoding of the length of the uNumber and is needed to decode
964 floats and doubles
965 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800966 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700967 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800968 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800969
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700970 memset(pDecodedItem, 0, sizeof(QCBORItem));
971
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800972 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800973
Laurence Lundbladeee851742020-01-08 08:37:05 -0800974 // Error out here if we got into trouble on the type and number. The
975 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700976 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700977 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700978 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800979
Laurence Lundbladeee851742020-01-08 08:37:05 -0800980 // At this point the major type and the value are valid. We've got
981 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800982 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700983 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
984 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800985 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700986 nReturn = QCBOR_ERR_BAD_INT;
987 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800988 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700989 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800991
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700992 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
993 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800994 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
995 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
996 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
997 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530998 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700999 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001000 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001001 }
1002 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001003
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001004 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
1005 case CBOR_MAJOR_TYPE_MAP: // Major type 5
1006 // Record the number of items in the array or map
1007 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
1008 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1009 goto Done;
1010 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001011 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001012 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001013 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001014 // type conversion OK because of check above
1015 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001016 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001017 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001018 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
1019 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001020 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001021
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001022 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001023 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001024 nReturn = QCBOR_ERR_BAD_INT;
1025 } else {
1026 pDecodedItem->val.uTagV = uNumber;
1027 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
1028 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001029 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001030
Laurence Lundbladeee851742020-01-08 08:37:05 -08001031 case CBOR_MAJOR_TYPE_SIMPLE:
1032 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001033 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001034 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001035
Laurence Lundbladeee851742020-01-08 08:37:05 -08001036 default:
1037 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001038 nReturn = QCBOR_ERR_UNSUPPORTED;
1039 break;
1040 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001041
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001042Done:
1043 return nReturn;
1044}
1045
1046
1047
1048/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001049 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001050 individual chunk items together into one QCBORItem using the string
1051 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001052
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301053 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001054 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001055static inline QCBORError
1056GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001057{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001058 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001059
1060 // Get pointer to string allocator. First use is to pass it to
1061 // GetNext_Item() when option is set to allocate for *every* string.
1062 // Second use here is to allocate space to coallese indefinite
1063 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001064 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1065 &(me->StringAllocator) :
1066 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001067
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001068 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001069 nReturn = GetNext_Item(&(me->InBuf),
1070 pDecodedItem,
1071 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001072 if(nReturn) {
1073 goto Done;
1074 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001075
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001076 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301077 // code in this function from here down can be eliminated. Run tests, except
1078 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001079
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001080 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001081 const uint8_t uStringType = pDecodedItem->uDataType;
1082 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001083 goto Done; // no need to do any work here on non-string types
1084 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001085
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001086 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301087 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001088 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001089 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001090
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301091 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001092 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001093 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1094 goto Done;
1095 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001096
Laurence Lundblade4b270642020-08-14 12:53:07 -07001097 // Loop getting chunks of the indefinite length string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001098 UsefulBufC FullString = NULLUsefulBufC;
1099
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001100 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001101 // Get item for next chunk
1102 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001103 // NULL string allocator passed here. Do not need to allocate
1104 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001105 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001106 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001107 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001108 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001109
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301110 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001111 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001112 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001113 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301114 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001115 break;
1116 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001117
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001118 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301119 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001120 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001121 if(StringChunkItem.uDataType != uStringType ||
1122 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001123 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001124 break;
1125 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001126
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301127 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001128 // The first time throurgh FullString.ptr is NULL and this is
1129 // equivalent to StringAllocator_Allocate()
1130 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1131 UNCONST_POINTER(FullString.ptr),
1132 FullString.len + StringChunkItem.val.string.len);
1133
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001134 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301135 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001136 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001137 break;
1138 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001139
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001140 // Copy new string chunk at the end of string so far.
1141 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001142 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001143
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001144 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1145 // Getting the item failed, clean up the allocated memory
1146 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001147 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001148
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001149Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001150 return nReturn;
1151}
1152
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001153
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001154static uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1155 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001156 return uTagVal;
1157 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001158 int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001159 return me->auMappedTags[x];
1160 }
1161}
1162
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001163/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001164 Gets all optional tag data items preceding a data item that is not an
1165 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001166 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001167static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001168GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001169{
Laurence Lundblade30816f22018-11-10 13:40:22 +07001170 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001171
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001172 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1173 CBOR_TAG_INVALID16,
1174 CBOR_TAG_INVALID16,
1175 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001176
Laurence Lundblade59289e52019-12-30 13:44:37 -08001177 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001178 for(;;) {
1179 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001180 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001181 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001182 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001183
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001184 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1185 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001186 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001187 break;
1188 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001189
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001190 // Is there room for the tag in the tags list?
1191 size_t uTagIndex;
1192 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001193 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001194 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001195 }
1196 }
1197 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001198 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001199 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001200
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001201 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001202 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001203 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001204 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001205 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001206 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001207 break;
1208 }
1209 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001210 // TODO: test this
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001211 break;
1212 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001213 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001214 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1215 // No room for the tag
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001216 // Should never happen as long as QCBOR_MAX_TAGS_PER_ITEM <= QCBOR_NUM_MAPPED_TAGS
1217 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001218 }
1219
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001220 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001221 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001222 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001223
1224 } else {
1225 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001226 }
1227 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001228
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001229Done:
1230 return nReturn;
1231}
1232
1233
1234/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001235 This layer takes care of map entries. It combines the label and data
1236 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001237 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001238static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001239GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001240{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001241 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001242 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001243 if(nReturn)
1244 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001245
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001246 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001247 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001248 goto Done;
1249 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001250
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001251 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1252 // In a map and caller wants maps decoded, not treated as arrays
1253
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001254 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001255 // If in a map and the right decoding mode, get the label
1256
Laurence Lundbladeee851742020-01-08 08:37:05 -08001257 // Save label in pDecodedItem and get the next which will
1258 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001259 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001260 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001261 if(nReturn)
1262 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001263
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301264 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001265
1266 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1267 // strings are always good labels
1268 pDecodedItem->label.string = LabelItem.val.string;
1269 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1270 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001271 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001272 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1273 goto Done;
1274 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1275 pDecodedItem->label.int64 = LabelItem.val.int64;
1276 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1277 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1278 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1279 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1280 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1281 pDecodedItem->label.string = LabelItem.val.string;
1282 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1283 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1284 } else {
1285 // label is not an int or a string. It is an arrray
1286 // or a float or such and this implementation doesn't handle that.
1287 // Also, tags on labels are ignored.
1288 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1289 goto Done;
1290 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001291 }
1292 } else {
1293 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001294 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1295 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1296 goto Done;
1297 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001298 // Decoding a map as an array
1299 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001300 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1301 // Cast is needed because of integer promotion
1302 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001303 }
1304 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001305
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001306Done:
1307 return nReturn;
1308}
1309
1310
Laurence Lundblade02625d42020-06-25 14:41:41 -07001311/*
1312 See if next item is a CBOR break. If it is, it is consumed,
1313 if not it is not consumed.
1314*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001315static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001316NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1317{
1318 *pbNextIsBreak = false;
1319 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001320 QCBORItem Peek;
1321 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1322 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1323 if(uReturn != QCBOR_SUCCESS) {
1324 return uReturn;
1325 }
1326 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001327 // It is not a break, rewind so it can be processed normally.
1328 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001329 } else {
1330 *pbNextIsBreak = true;
1331 }
1332 }
1333
1334 return QCBOR_SUCCESS;
1335}
1336
1337
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001338/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001339 An item was just consumed, now figure out if it was the
1340 end of an array or map that can be closed out. That
1341 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001342*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001343static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001344{
1345 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001346
Laurence Lundblade642282a2020-06-23 12:00:33 -07001347 /* This loops ascending nesting levels as long as there is ascending to do */
1348 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1349
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001350 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001351 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001352 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1353 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001354 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001355 break;
1356 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001357 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001358
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001359 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001360 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001361 bool bIsBreak = false;
1362 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1363 if(uReturn != QCBOR_SUCCESS) {
1364 goto Done;
1365 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001366
1367 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001368 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001369 break;
1370 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001371
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001372 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001373 /*
1374 Break occurred inside a bstr-wrapped CBOR or
1375 in the top level sequence. This is always an
1376 error because neither are an indefinte length
1377 map/array.
1378 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001379 uReturn = QCBOR_ERR_BAD_BREAK;
1380 goto Done;
1381 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07001382
Laurence Lundblade02625d42020-06-25 14:41:41 -07001383 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001384 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001385
Laurence Lundblade02625d42020-06-25 14:41:41 -07001386 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001387
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001388 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001389 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001390 /* 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 -07001391 if(bMarkEnd) {
1392 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001393 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001394
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001395 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001396 break;
1397 }
1398
1399 /* Finally, actually ascend one level. */
1400 DecodeNesting_Ascend(&(pMe->nesting));
1401 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001402
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001403 uReturn = QCBOR_SUCCESS;
1404
1405Done:
1406 return uReturn;
1407}
1408
1409
1410/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001411 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001412 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1413 indefinte length maps and arrays by looking at the item count or
1414 finding CBOR breaks. It detects the ends of the top-level sequence
1415 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001416 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001417static QCBORError
1418QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001419{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001420 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001421 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001422
Laurence Lundblade642282a2020-06-23 12:00:33 -07001423 /*
1424 If out of bytes to consume, it is either the end of the top-level
1425 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001426
Laurence Lundblade642282a2020-06-23 12:00:33 -07001427 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1428 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1429 CBOR is exited, the length is set back to the top-level's length
1430 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001431 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001432 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001433 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001434 goto Done;
1435 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001436
Laurence Lundblade642282a2020-06-23 12:00:33 -07001437 /*
1438 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001439 array. The check for the end of an indefinite length array is
1440 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001441 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001442 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001443 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001444 goto Done;
1445 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001446
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001447 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001448 uReturn = GetNext_MapEntry(me, pDecodedItem);
1449 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001450 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001451 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301452
Laurence Lundblade642282a2020-06-23 12:00:33 -07001453 /*
1454 Breaks ending arrays/maps are always processed at the end of this
1455 function. They should never show up here.
1456 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301457 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001458 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301459 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301460 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001461
Laurence Lundblade642282a2020-06-23 12:00:33 -07001462 /*
1463 Record the nesting level for this data item before processing any
1464 of decrementing and descending.
1465 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001466 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001467
Laurence Lundblade642282a2020-06-23 12:00:33 -07001468
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001469 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001470 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001471 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001472 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001473
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001474 Empty indefinite length maps and arrays are descended into, but then ascended out
Laurence Lundblade02625d42020-06-25 14:41:41 -07001475 of in the next chunk of code.
1476
1477 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001478 encloses them so a decrement needs to be done for them too, but
1479 that is done only when all the items in them have been
1480 processed, not when they are opened with the exception of an
1481 empty map or array.
1482 */
1483 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1484 pDecodedItem->uDataType,
1485 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001486 if(uReturn != QCBOR_SUCCESS) {
1487 goto Done;
1488 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001489 }
1490
Laurence Lundblade02625d42020-06-25 14:41:41 -07001491 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1492 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1493 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001494 /*
1495 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001496 - A non-aggregate like an integer or string
1497 - An empty definite length map or array
1498 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001499
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001500 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001501 definite length map/array and break detection for an indefinite
1502 length map/array. If the end of the map/array was reached, then
1503 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001504 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001505 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001506 if(uReturn) {
1507 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001508 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301509 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001510
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001511 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001512 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001513 Tell the caller what level is next. This tells them what
1514 maps/arrays were closed out and makes it possible for them to
1515 reconstruct the tree with just the information returned in
1516 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001517 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001518 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001519 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001520 pDecodedItem->uNextNestLevel = 0;
1521 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001522 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001523 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001524
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001525Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001526 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001527 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001528 memset(pDecodedItem, 0, sizeof(QCBORItem));
1529 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001530 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001531}
1532
1533
Laurence Lundblade59289e52019-12-30 13:44:37 -08001534/*
1535 Mostly just assign the right data type for the date string.
1536 */
1537inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1538{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001539 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1540 return QCBOR_ERR_BAD_OPT_TAG;
1541 }
1542
1543 const UsefulBufC Temp = pDecodedItem->val.string;
1544 pDecodedItem->val.dateString = Temp;
1545 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1546 return QCBOR_SUCCESS;
1547}
1548
1549
1550/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001551 The epoch formatted date. Turns lots of different forms of encoding
1552 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001553 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001554static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001555{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001556 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001557
1558 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1559
1560 switch (pDecodedItem->uDataType) {
1561
1562 case QCBOR_TYPE_INT64:
1563 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1564 break;
1565
1566 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001567 // This only happens for CBOR type 0 > INT64_MAX so it is
1568 // always an overflow.
1569 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1570 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001571 break;
1572
1573 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001574 case QCBOR_TYPE_FLOAT:
1575#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001576 {
1577 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001578 // conversion to an int64_t to be able to detect doubles that
1579 // are too large to fit into an int64_t. A double has 52
1580 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1581 // to a double actually causes a round up which is bad and
1582 // wrong for the comparison because it will allow conversion
1583 // of doubles that can't fit into a uint64_t. To remedy this
1584 // INT64_MAX - 0x7ff is used as the cutoff point because if
1585 // that value rounds up in conversion to double it will still
1586 // be less than INT64_MAX. 0x7ff is picked because it has 11
1587 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001588 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001589 // INT64_MAX seconds is on the order of 10 billion years, and
1590 // the earth is less than 5 billion years old, so for most
1591 // uses this conversion error won't occur even though doubles
1592 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001593 //
1594 // Without the 0x7ff there is a ~30 minute range of time
1595 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001596 // where this code would go wrong. Some compilers
1597 // will generate warnings or errors without the 0x7ff
1598 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001599 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1600 pDecodedItem->val.dfnum :
1601 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001602 if(isnan(d) ||
1603 d > (double)(INT64_MAX - 0x7ff) ||
1604 d < (double)(INT64_MIN + 0x7ff)) {
1605 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001606 goto Done;
1607 }
1608 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001609 pDecodedItem->val.epochDate.fSecondsFraction =
1610 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001611 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001612#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001613
Laurence Lundbladec7114722020-08-13 05:11:40 -07001614 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001615 goto Done;
1616
Laurence Lundblade9682a532020-06-06 18:33:04 -07001617#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001618 break;
1619
1620 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001621 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001622 goto Done;
1623 }
1624 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1625
1626Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001627 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001628}
1629
1630
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001631/*
1632 Mostly just assign the right data type for the bignum.
1633 */
1634inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1635{
1636 // Stack Use: UsefulBuf 1 -- 16
1637 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1638 return QCBOR_ERR_BAD_OPT_TAG;
1639 }
1640 const UsefulBufC Temp = pDecodedItem->val.string;
1641 pDecodedItem->val.bigNum = Temp;
1642 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1643 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1644 : QCBOR_TYPE_NEGBIGNUM);
1645 return QCBOR_SUCCESS;
1646}
1647
1648
Laurence Lundblade59289e52019-12-30 13:44:37 -08001649#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1650/*
1651 Decode decimal fractions and big floats.
1652
1653 When called pDecodedItem must be the array that is tagged as a big
1654 float or decimal fraction, the array that has the two members, the
1655 exponent and mantissa.
1656
1657 This will fetch and decode the exponent and mantissa and put the
1658 result back into pDecodedItem.
1659 */
1660inline static QCBORError
1661QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1662{
1663 QCBORError nReturn;
1664
1665 // --- Make sure it is an array; track nesting level of members ---
1666 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1667 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1668 goto Done;
1669 }
1670
1671 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001672 // definite length arrays, but not for indefnite. Instead remember
1673 // the nesting level the two integers must be at, which is one
1674 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001675 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1676
1677 // --- Is it a decimal fraction or a bigfloat? ---
1678 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1679 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1680
1681 // --- Get the exponent ---
1682 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001683 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001684 if(nReturn != QCBOR_SUCCESS) {
1685 goto Done;
1686 }
1687 if(exponentItem.uNestingLevel != nNestLevel) {
1688 // Array is empty or a map/array encountered when expecting an int
1689 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1690 goto Done;
1691 }
1692 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1693 // Data arriving as an unsigned int < INT64_MAX has been converted
1694 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1695 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1696 // will be too large for this to handle and thus an error that will
1697 // get handled in the next else.
1698 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1699 } else {
1700 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1701 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1702 goto Done;
1703 }
1704
1705 // --- Get the mantissa ---
1706 QCBORItem mantissaItem;
1707 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1708 if(nReturn != QCBOR_SUCCESS) {
1709 goto Done;
1710 }
1711 if(mantissaItem.uNestingLevel != nNestLevel) {
1712 // Mantissa missing or map/array encountered when expecting number
1713 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1714 goto Done;
1715 }
1716 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1717 // Data arriving as an unsigned int < INT64_MAX has been converted
1718 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1719 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1720 // will be too large for this to handle and thus an error that
1721 // will get handled in an else below.
1722 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1723 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1724 // Got a good big num mantissa
1725 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1726 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001727 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1728 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1729 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001730 } else {
1731 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1732 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1733 goto Done;
1734 }
1735
1736 // --- Check that array only has the two numbers ---
1737 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001738 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001739 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1740 goto Done;
1741 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07001742 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel; // TODO: make sure this is right
Laurence Lundblade59289e52019-12-30 13:44:37 -08001743
1744Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001745 return nReturn;
1746}
1747#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1748
1749
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001750inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1751{
1752 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1753 return QCBOR_ERR_BAD_OPT_TAG;
1754 }
1755 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1756 return QCBOR_SUCCESS;
1757}
1758
1759
1760inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1761{
1762 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1763 return QCBOR_ERR_BAD_OPT_TAG;
1764 }
1765 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1766 return QCBOR_SUCCESS;
1767}
1768
1769
1770inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1771{
1772 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1773 return QCBOR_ERR_BAD_OPT_TAG;
1774 }
1775 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1776 return QCBOR_SUCCESS;
1777}
1778
1779
1780inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1781{
1782 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1783 return QCBOR_ERR_BAD_OPT_TAG;
1784 }
1785 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1786 return QCBOR_SUCCESS;
1787}
1788
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001789
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001790inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1791{
1792 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1793 return QCBOR_ERR_BAD_OPT_TAG;
1794 }
1795 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1796 return QCBOR_SUCCESS;
1797}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001798
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001799
1800inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1801{
1802 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1803 return QCBOR_ERR_BAD_OPT_TAG;
1804 }
1805 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
1806 return QCBOR_SUCCESS;
1807}
1808
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001809
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001810inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1811{
1812 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1813 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001814 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001815 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1816 } else {
1817 return QCBOR_ERR_BAD_OPT_TAG;
1818 }
1819 return QCBOR_SUCCESS;
1820}
1821
1822
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001823inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1824{
1825 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1826 return QCBOR_ERR_BAD_OPT_TAG;
1827 }
1828 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1829 return QCBOR_SUCCESS;
1830}
1831
1832
Laurence Lundblade59289e52019-12-30 13:44:37 -08001833/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001834 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001835 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001836QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001837QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001838{
1839 QCBORError nReturn;
1840
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001841 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001842 if(nReturn != QCBOR_SUCCESS) {
1843 goto Done;
1844 }
1845
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001846 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1847 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001848
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001849 // Many of the functions here only just map a CBOR tag to
1850 // a QCBOR_TYPE for a string and could probably be
1851 // implemented with less object code. This implementation
1852 // of string types takes about 120 bytes of object code
1853 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001854 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001855 nReturn = DecodeDateString(pDecodedItem);
1856 break;
1857
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001858 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001859 nReturn = DecodeDateEpoch(pDecodedItem);
1860 break;
1861
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001862 case CBOR_TAG_POS_BIGNUM:
1863 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001864 nReturn = DecodeBigNum(pDecodedItem);
1865 break;
1866
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001867 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1868 case CBOR_TAG_DECIMAL_FRACTION:
1869 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001870 // For aggregate tagged types, what goes into pTags is only collected
1871 // from the surrounding data item, not the contents, so pTags is not
1872 // passed on here.
1873
1874 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1875 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001876 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001877
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001878 case CBOR_TAG_CBOR:
1879 nReturn = DecodeWrappedCBOR(pDecodedItem);
1880 break;
1881
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001882 case CBOR_TAG_CBOR_SEQUENCE:
1883 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1884 break;
1885
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001886 case CBOR_TAG_URI:
1887 nReturn = DecodeURI(pDecodedItem);
1888 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001889
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001890 case CBOR_TAG_B64URL:
1891 nReturn = DecodeB64URL(pDecodedItem);
1892 break;
1893
1894 case CBOR_TAG_B64:
1895 nReturn = DecodeB64(pDecodedItem);
1896 break;
1897
1898 case CBOR_TAG_MIME:
1899 case CBOR_TAG_BINARY_MIME:
1900 nReturn = DecodeMIME(pDecodedItem);
1901 break;
1902
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001903 case CBOR_TAG_REGEX:
1904 nReturn = DecodeRegex(pDecodedItem);
1905 break;
1906
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001907 case CBOR_TAG_BIN_UUID:
1908 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001909 break;
1910
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001911 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001912 // The end of the tag list or no tags
1913 // Successful exit from the loop.
1914 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001915
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001916 default:
1917 // A tag that is not understood
1918 // A successful exit from the loop
1919 goto Done;
1920
1921 }
1922 if(nReturn != QCBOR_SUCCESS) {
1923 goto Done;
1924 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001925 }
1926
1927Done:
1928 if(nReturn != QCBOR_SUCCESS) {
1929 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1930 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1931 }
1932 return nReturn;
1933}
1934
1935
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001936QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1937{
1938 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1939
1940 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1941
1942 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundblade78f7b932020-07-28 20:02:25 -07001943 // TODO: undo the level tracking (or don't do it)
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001944
1945 return uErr;
1946}
1947
1948
Laurence Lundblade59289e52019-12-30 13:44:37 -08001949/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001950 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001951 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001952QCBORError
1953QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1954 QCBORItem *pDecodedItem,
1955 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001956{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001957 QCBORError nReturn;
1958
1959 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1960 if(nReturn != QCBOR_SUCCESS) {
1961 return nReturn;
1962 }
1963
1964 if(pTags != NULL) {
1965 pTags->uNumUsed = 0;
1966 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001967 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001968 break;
1969 }
1970 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1971 return QCBOR_ERR_TOO_MANY_TAGS;
1972 }
1973 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1974 pTags->uNumUsed++;
1975 }
1976 }
1977
1978 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001979}
1980
1981
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001982/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301983 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301984 next one down. If a layer has no work to do for a particular item
1985 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001986
Laurence Lundblade59289e52019-12-30 13:44:37 -08001987 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1988 tagged data items, turning them into the local C representation.
1989 For the most simple it is just associating a QCBOR_TYPE with the data. For
1990 the complex ones that an aggregate of data items, there is some further
1991 decoding and a little bit of recursion.
1992
1993 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301994 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301995 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001996 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001997
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301998 - GetNext_MapEntry -- This handles the combining of two
1999 items, the label and the data, that make up a map entry.
2000 It only does work on maps. It combines the label and data
2001 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002002
Laurence Lundblade59289e52019-12-30 13:44:37 -08002003 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2004 tags into bit flags associated with the data item. No actual decoding
2005 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002006
Laurence Lundblade59289e52019-12-30 13:44:37 -08002007 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302008 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302009 string allocater to create contiguous space for the item. It
2010 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002011
Laurence Lundblade59289e52019-12-30 13:44:37 -08002012 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2013 atomic data item has a "major type", an integer "argument" and optionally
2014 some content. For text and byte strings, the content is the bytes
2015 that make up the string. These are the smallest data items that are
2016 considered to be well-formed. The content may also be other data items in
2017 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002018
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002019 Roughly this takes 300 bytes of stack for vars. Need to
2020 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002021
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302022 */
2023
2024
2025/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002026 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002027 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002028bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002029 const QCBORItem *pItem,
2030 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002031{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002032 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002033 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002034 break;
2035 }
2036 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002037 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002038 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002039 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002040
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002041 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002042}
2043
2044
2045/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002046 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002047 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002048QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002049{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002050 QCBORError uReturn = me->uLastError;
2051
2052 if(uReturn != QCBOR_SUCCESS) {
2053 goto Done;
2054 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002055
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002056 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002057 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002058 uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002059 goto Done;
2060 }
2061
2062 // Error out if not all the bytes are consumed
2063 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002064 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002065 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002066
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002067Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302068 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002069 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002070 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002071
Laurence Lundblade085d7952020-07-24 10:26:30 -07002072 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002073}
2074
2075
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002076/*
2077Public function, see header qcbor/qcbor_decode.h file
2078*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002079uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2080 const QCBORItem *pItem,
2081 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002082{
2083 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
2084 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002085 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002086 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002087 }
2088}
2089
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002090
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002091/*
2092
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002093Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002094
Laurence Lundbladeee851742020-01-08 08:37:05 -08002095 - Hit end of input before it was expected while decoding type and
2096 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002097
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002098 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002099
Laurence Lundbladeee851742020-01-08 08:37:05 -08002100 - Hit end of input while decoding a text or byte string
2101 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002102
Laurence Lundbladeee851742020-01-08 08:37:05 -08002103 - Encountered conflicting tags -- e.g., an item is tagged both a date
2104 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002105
Laurence Lundbladeee851742020-01-08 08:37:05 -08002106 - Encontered an array or mapp that has too many items
2107 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002108
Laurence Lundbladeee851742020-01-08 08:37:05 -08002109 - Encountered array/map nesting that is too deep
2110 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002111
Laurence Lundbladeee851742020-01-08 08:37:05 -08002112 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2113 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002114
Laurence Lundbladeee851742020-01-08 08:37:05 -08002115 - The type of a map label is not a string or int
2116 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002117
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002118 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002119
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002120 */
2121
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002122
2123
Laurence Lundbladef6531662018-12-04 10:42:22 +09002124
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002125/* ===========================================================================
2126 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002127
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002128 This implements a simple sting allocator for indefinite length
2129 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2130 implements the function type QCBORStringAllocate and allows easy
2131 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002132
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002133 This particular allocator is built-in for convenience. The caller
2134 can implement their own. All of this following code will get
2135 dead-stripped if QCBORDecode_SetMemPool() is not called.
2136
2137 This is a very primitive memory allocator. It does not track
2138 individual allocations, only a high-water mark. A free or
2139 reallocation must be of the last chunk allocated.
2140
2141 The size of the pool and offset to free memory are packed into the
2142 first 8 bytes of the memory pool so we don't have to keep them in
2143 the decode context. Since the address of the pool may not be
2144 aligned, they have to be packed and unpacked as if they were
2145 serialized data of the wire or such.
2146
2147 The sizes packed in are uint32_t to be the same on all CPU types
2148 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002149 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002150
2151
Laurence Lundbladeee851742020-01-08 08:37:05 -08002152static inline int
2153MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002154{
2155 // Use of UsefulInputBuf is overkill, but it is convenient.
2156 UsefulInputBuf UIB;
2157
Laurence Lundbladeee851742020-01-08 08:37:05 -08002158 // Just assume the size here. It was checked during SetUp so
2159 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002160 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2161 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2162 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2163 return UsefulInputBuf_GetError(&UIB);
2164}
2165
2166
Laurence Lundbladeee851742020-01-08 08:37:05 -08002167static inline int
2168MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002169{
2170 // Use of UsefulOutBuf is overkill, but convenient. The
2171 // length check performed here is useful.
2172 UsefulOutBuf UOB;
2173
2174 UsefulOutBuf_Init(&UOB, Pool);
2175 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2176 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2177 return UsefulOutBuf_GetError(&UOB);
2178}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002179
2180
2181/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002182 Internal function for an allocation, reallocation free and destuct.
2183
2184 Having only one function rather than one each per mode saves space in
2185 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002186
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002187 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2188 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002189static UsefulBuf
2190MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002191{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002192 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002193
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002194 uint32_t uPoolSize;
2195 uint32_t uFreeOffset;
2196
2197 if(uNewSize > UINT32_MAX) {
2198 // This allocator is only good up to 4GB. This check should
2199 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2200 goto Done;
2201 }
2202 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2203
2204 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2205 goto Done;
2206 }
2207
2208 if(uNewSize) {
2209 if(pMem) {
2210 // REALLOCATION MODE
2211 // Calculate pointer to the end of the memory pool. It is
2212 // assumed that pPool + uPoolSize won't wrap around by
2213 // assuming the caller won't pass a pool buffer in that is
2214 // not in legitimate memory space.
2215 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2216
2217 // Check that the pointer for reallocation is in the range of the
2218 // pool. This also makes sure that pointer math further down
2219 // doesn't wrap under or over.
2220 if(pMem >= pPool && pMem < pPoolEnd) {
2221 // Offset to start of chunk for reallocation. This won't
2222 // wrap under because of check that pMem >= pPool. Cast
2223 // is safe because the pool is always less than UINT32_MAX
2224 // because of check in QCBORDecode_SetMemPool().
2225 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2226
2227 // Check to see if the allocation will fit. uPoolSize -
2228 // uMemOffset will not wrap under because of check that
2229 // pMem is in the range of the uPoolSize by check above.
2230 if(uNewSize <= uPoolSize - uMemOffset) {
2231 ReturnValue.ptr = pMem;
2232 ReturnValue.len = uNewSize;
2233
2234 // Addition won't wrap around over because uNewSize was
2235 // checked to be sure it is less than the pool size.
2236 uFreeOffset = uMemOffset + uNewSize32;
2237 }
2238 }
2239 } else {
2240 // ALLOCATION MODE
2241 // uPoolSize - uFreeOffset will not underflow because this
2242 // pool implementation makes sure uFreeOffset is always
2243 // smaller than uPoolSize through this check here and
2244 // reallocation case.
2245 if(uNewSize <= uPoolSize - uFreeOffset) {
2246 ReturnValue.len = uNewSize;
2247 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002248 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002249 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002250 }
2251 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002252 if(pMem) {
2253 // FREE MODE
2254 // Cast is safe because of limit on pool size in
2255 // QCBORDecode_SetMemPool()
2256 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2257 } else {
2258 // DESTRUCT MODE
2259 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002260 }
2261 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002262
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002263 UsefulBuf Pool = {pPool, uPoolSize};
2264 MemPool_Pack(Pool, uFreeOffset);
2265
2266Done:
2267 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002268}
2269
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002270
Laurence Lundbladef6531662018-12-04 10:42:22 +09002271/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002272 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002273 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002274QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2275 UsefulBuf Pool,
2276 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002277{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002278 // The pool size and free mem offset are packed into the beginning
2279 // of the pool memory. This compile time check make sure the
2280 // constant in the header is correct. This check should optimize
2281 // down to nothing.
2282 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002283 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002284 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002285
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002286 // The pool size and free offset packed in to the beginning of pool
2287 // memory are only 32-bits. This check will optimize out on 32-bit
2288 // machines.
2289 if(Pool.len > UINT32_MAX) {
2290 return QCBOR_ERR_BUFFER_TOO_LARGE;
2291 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002292
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002293 // This checks that the pool buffer given is big enough.
2294 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2295 return QCBOR_ERR_BUFFER_TOO_SMALL;
2296 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002297
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002298 pMe->StringAllocator.pfAllocator = MemPool_Function;
2299 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2300 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002301
Laurence Lundblade30816f22018-11-10 13:40:22 +07002302 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002303}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002304
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002305
2306
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002307
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002308
2309
2310/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002311 Consume an entire map or array (and do next to
2312 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002313 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002314static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002315ConsumeItem(QCBORDecodeContext *pMe,
2316 const QCBORItem *pItemToConsume,
2317 uint_fast8_t *puNextNestLevel)
2318{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002319 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002320 QCBORItem Item;
2321
Laurence Lundblade02625d42020-06-25 14:41:41 -07002322 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002323
Laurence Lundblade02625d42020-06-25 14:41:41 -07002324 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002325 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002326
Laurence Lundblade1341c592020-04-11 14:19:05 -07002327 /* This works for definite and indefinite length
2328 * maps and arrays by using the nesting level
2329 */
2330 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002331 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade4b270642020-08-14 12:53:07 -07002332 if( QCBORDecode_IsNotWellFormed(uReturn)) {
2333 // TODO: also resource limit errors
Laurence Lundblade1341c592020-04-11 14:19:05 -07002334 goto Done;
2335 }
2336 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002337
Laurence Lundblade1341c592020-04-11 14:19:05 -07002338 if(puNextNestLevel != NULL) {
2339 *puNextNestLevel = Item.uNextNestLevel;
2340 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002341 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002342
Laurence Lundblade1341c592020-04-11 14:19:05 -07002343 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002344 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002345 if(puNextNestLevel != NULL) {
2346 /* Just pass the nesting level through */
2347 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2348 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002349 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002350 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002351
2352Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002353 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002354}
2355
2356
Laurence Lundblade1341c592020-04-11 14:19:05 -07002357/* Return true if the labels in Item1 and Item2 are the same.
2358 Works only for integer and string labels. Returns false
2359 for any other type. */
2360static inline bool
2361MatchLabel(QCBORItem Item1, QCBORItem Item2)
2362{
2363 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2364 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2365 return true;
2366 }
2367 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002368 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002369 return true;
2370 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002371 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002372 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2373 return true;
2374 }
2375 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2376 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2377 return true;
2378 }
2379 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002380
Laurence Lundblade1341c592020-04-11 14:19:05 -07002381 /* Other label types are never matched */
2382 return false;
2383}
2384
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002385
2386/*
2387 Returns true if Item1 and Item2 are the same type
2388 or if either are of QCBOR_TYPE_ANY.
2389 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002390static inline bool
2391MatchType(QCBORItem Item1, QCBORItem Item2)
2392{
2393 if(Item1.uDataType == Item2.uDataType) {
2394 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002395 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002396 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002397 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002398 return true;
2399 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002400 return false;
2401}
2402
2403
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002404/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002405 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002406
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002407 @param[in] pMe The decode context to search.
2408 @param[in,out] pItemArray The items to search for and the items found.
2409 @param[out] puOffset Byte offset of last item matched.
2410 @param[in] pCBContext Context for the not-found item call back.
2411 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002412
2413 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2414
2415 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label) were found for one of the labels being search for. This duplicate detection is only performed for items in pItemArray, not every item in the map.
2416
2417 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2418
2419 @retval Also errors returned by QCBORDecode_GetNext().
2420
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002421 On input pItemArray contains a list of labels and data types
2422 of items to be found.
2423
2424 On output the fully retrieved items are filled in with
2425 values and such. The label was matched, so it never changes.
2426
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002427 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002428 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002429static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002430MapSearch(QCBORDecodeContext *pMe,
2431 QCBORItem *pItemArray,
2432 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002433 void *pCBContext,
2434 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002435{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002436 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002437 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002438
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002439 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002440 uReturn = pMe->uLastError;
2441 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002442 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002443
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002444 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002445 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2446 /* QCBOR_TYPE_NONE as first item indicates just looking
2447 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002448 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2449 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002450 }
2451
Laurence Lundblade085d7952020-07-24 10:26:30 -07002452 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2453 // It is an empty bounded array or map
2454 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2455 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002456 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002457 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002458 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002459 // Nothing is ever found in an empty array or map. All items
2460 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002461 uReturn = QCBOR_SUCCESS;
2462 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002463 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002464 }
2465
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002466 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002467 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2468
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002469 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002470 UsefulInputBuf_Seek(&(pMe->InBuf),
2471 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002472
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002473 /*
2474 Loop over all the items in the map. They could be
2475 deeply nested and this should handle both definite
2476 and indefinite length maps and arrays, so this
2477 adds some complexity.
2478 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002479 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002480 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002481 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002482 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002483 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002484
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002485 /* Get the item */
2486 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002487 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002488 if(QCBORDecode_IsNotWellFormed(uReturn)) {
2489 /* Got non-well-formed CBOR so map can't even be decoded. */
Laurence Lundblade4b270642020-08-14 12:53:07 -07002490 // TODO: also bail out on implementation limits like array too big
Laurence Lundblade1341c592020-04-11 14:19:05 -07002491 goto Done;
2492 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002493
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002494 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002495 bool bMatched = false;
2496 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
Laurence Lundblade4b270642020-08-14 12:53:07 -07002497 // TODO: have label filled in on invalid CBOR so error reporting
2498 // can work a lot better.
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002499 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002500 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002501 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2502 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002503 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002504 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002505 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002506 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002507 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002508 goto Done;
2509 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002510
Laurence Lundblade1341c592020-04-11 14:19:05 -07002511 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002512 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002513 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002514 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002515 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002516 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002517 bMatched = true;
2518 }
2519 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002520
2521
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002522 if(!bMatched && pfCallback != NULL) {
2523 /*
2524 Call the callback on unmatched labels.
2525 (It is tempting to do duplicate detection here, but that would
2526 require dynamic memory allocation because the number of labels
2527 that might be encountered is unbounded.)
2528 */
2529 uReturn = (*pfCallback)(pCBContext, &Item);
2530 if(uReturn != QCBOR_SUCCESS) {
2531 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002532 }
2533 }
2534
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002535 /*
2536 Consume the item whether matched or not. This
2537 does the work of traversing maps and array and
2538 everything in them. In this loop only the
2539 items at the current nesting level are examined
2540 to match the labels.
2541 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002542 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002543 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002544 goto Done;
2545 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002546
2547 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002548
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002549 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002550
2551 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002552 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2553 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002554
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002555 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002556 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2557
2558 Done2:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002559 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
2560 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002561 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002562 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002563 }
2564 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002565
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002566 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002567}
2568
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002569
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002570/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002571 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002572*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002573void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2574 int64_t nLabel,
2575 uint8_t uQcborType,
2576 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002577{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002578 if(pMe->uLastError != QCBOR_SUCCESS) {
2579 return;
2580 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002581
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002582 QCBORItem OneItemSeach[2];
2583 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2584 OneItemSeach[0].label.int64 = nLabel;
2585 OneItemSeach[0].uDataType = uQcborType;
2586 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002587
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002588 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2589 if(uReturn != QCBOR_SUCCESS) {
2590 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002591 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002592 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002593 uReturn = QCBOR_ERR_NOT_FOUND;
2594 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002595 }
2596
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002597 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002598
2599 Done:
2600 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002601}
2602
2603
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002604/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002605 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002606*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002607void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2608 const char *szLabel,
2609 uint8_t uQcborType,
2610 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002611{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002612 if(pMe->uLastError != QCBOR_SUCCESS) {
2613 return;
2614 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002615
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002616 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002617 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2618 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2619 OneItemSeach[0].uDataType = uQcborType;
2620 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002621
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002622 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2623 if(uReturn != QCBOR_SUCCESS) {
2624 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002625 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002626 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002627 uReturn = QCBOR_ERR_NOT_FOUND;
2628 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002629 }
2630
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002631 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002632
2633Done:
2634 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002635}
2636
2637
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002638
2639static QCBORError CheckTypeList(uint8_t uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
2640{
2641 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2642 if(uDataType == puTypeList[i]) {
2643 return QCBOR_SUCCESS;
2644 }
2645 }
2646 return QCBOR_ERR_UNEXPECTED_TYPE;
2647}
2648
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002649
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002650/**
2651 @param[in] TagSpec Specification for matching tags.
2652 @param[in] uDataType A QCBOR data type
2653
2654 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2655 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2656
2657 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2658 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002659static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002660{
Laurence Lundbladef9175a92020-07-30 21:35:45 -07002661 if(TagSpec.uTagRequirement == QCBOR_TAG_REQUIREMENT_MATCH_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002662 // Must match the tag and only the tag
2663 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002664 }
2665
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002666 QCBORError uReturn = CheckTypeList(uDataType, TagSpec.uAllowedContentTypes);
2667 if(uReturn == QCBOR_SUCCESS) {
2668 return QCBOR_SUCCESS;
2669 }
2670
Laurence Lundbladef9175a92020-07-30 21:35:45 -07002671 if(TagSpec.uTagRequirement == QCBOR_TAG_REQUIREMENT_NO_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002672 /* Must match the content type and only the content type.
2673 There was no match just above so it is a fail. */
2674 return QCBOR_ERR_UNEXPECTED_TYPE;
2675 }
2676
2677 /* If here it can match either the tag or the content
2678 and it hasn't matched the content, so the end
2679 result is whether it matches the tag. This is
2680 also the case that the CBOR standard discourages. */
2681
2682 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002683}
2684
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002685
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002686// Semi-private
2687// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002688void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2689 int64_t nLabel,
2690 TagSpecification TagSpec,
2691 QCBORItem *pItem)
2692{
2693 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2694 if(pMe->uLastError != QCBOR_SUCCESS) {
2695 return;
2696 }
2697
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002698 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002699}
2700
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002701// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002702void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2703 const char *szLabel,
2704 TagSpecification TagSpec,
2705 QCBORItem *pItem)
2706{
2707 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2708 if(pMe->uLastError != QCBOR_SUCCESS) {
2709 return;
2710 }
2711
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002712 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002713}
2714
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002715// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002716void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2717 int64_t nLabel,
2718 TagSpecification TagSpec,
2719 UsefulBufC *pString)
2720{
2721 QCBORItem Item;
2722 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2723 if(pMe->uLastError == QCBOR_SUCCESS) {
2724 *pString = Item.val.string;
2725 }
2726}
2727
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002728// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002729void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2730 const char * szLabel,
2731 TagSpecification TagSpec,
2732 UsefulBufC *pString)
2733{
2734 QCBORItem Item;
2735 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2736 if(pMe->uLastError == QCBOR_SUCCESS) {
2737 *pString = Item.val.string;
2738 }
2739}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002740
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 Lundbladed8c82c52020-06-12 22:15:52 -07002744QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2745{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002746 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002747}
2748
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002749/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002750 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002751*/
2752QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2753 QCBORItem *pItemList,
2754 void *pCallbackCtx,
2755 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002756{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002757 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002758}
2759
2760
Laurence Lundblade34691b92020-05-18 22:25:25 -07002761static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002762{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002763 // TODO: check that only one item is in pSearch?
Laurence Lundblade34691b92020-05-18 22:25:25 -07002764 if(pMe->uLastError != QCBOR_SUCCESS) {
2765 // Already in error state; do nothing.
2766 return;
2767 }
2768
2769 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002770 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002771 if(pMe->uLastError != QCBOR_SUCCESS) {
2772 return;
2773 }
2774
Laurence Lundblade085d7952020-07-24 10:26:30 -07002775 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
2776 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
2777 return;
2778 }
2779
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002780 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002781 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002782
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002783 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002784 be at the right place.
2785
2786 The UsefulInBuf offset could be anywhere, so no assumption is
2787 made about it.
2788
2789 No assumption is made about the pre-order nesting level either.
2790
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002791 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002792 the map level that is being entered.
2793 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002794 /* Seek to the data item that is the map or array */
2795 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002796
2797 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002798
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002799 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002800}
2801
2802
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002803/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002804 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002805*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002806void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002807{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002808 QCBORItem OneItemSeach[2];
2809 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2810 OneItemSeach[0].label.int64 = nLabel;
2811 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2812 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002813
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002814 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002815 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002816}
2817
2818
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002819/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002820 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002821*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002822void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002823{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002824 QCBORItem OneItemSeach[2];
2825 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2826 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2827 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2828 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002829
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002830 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002831}
2832
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002833/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002834 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002835*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002836void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002837{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002838 QCBORItem OneItemSeach[2];
2839 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2840 OneItemSeach[0].label.int64 = nLabel;
2841 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2842 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002843
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002844 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002845}
2846
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002847/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002848 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002849*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002850void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2851{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002852 QCBORItem OneItemSeach[2];
2853 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2854 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2855 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2856 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002857
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002858 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002859}
2860
2861
Laurence Lundblade02625d42020-06-25 14:41:41 -07002862// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002863void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002864{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002865 QCBORError uErr;
2866
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002867 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002868 if(pMe->uLastError != QCBOR_SUCCESS) {
2869 // Already in error state; do nothing.
2870 return;
2871 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002872
2873 /* Get the data item that is the map that is being searched */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002874 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002875 uErr = QCBORDecode_GetNext(pMe, &Item);
2876 if(uErr != QCBOR_SUCCESS) {
2877 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002878 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002879 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002880 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
2881 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002882 }
2883
Laurence Lundbladef0499502020-08-01 11:55:57 -07002884 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07002885 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002886 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
2887 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002888 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002889 pMe->nesting.pCurrent->u.ma.uCountCursor++;
2890 }
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002891 // Special case to increment nesting level for zero-length maps and arrays entered in bounded mode.
2892 DecodeNesting_Descend(&(pMe->nesting), uType);
2893 }
2894
Laurence Lundblade02625d42020-06-25 14:41:41 -07002895 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002896
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002897 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
2898 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002899
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002900Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002901 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002902}
2903
Laurence Lundblade02625d42020-06-25 14:41:41 -07002904
2905/*
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002906 This is the common work for exiting a level that is a bounded map, array or bstr
2907 wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07002908
2909 One chunk of work is to set up the pre-order traversal so it is at
2910 the item just after the bounded map, array or bstr that is being
2911 exited. This is somewhat complex.
2912
2913 The other work is to level-up the bounded mode to next higest bounded
2914 mode or the top level if there isn't one.
2915 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002916static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002917ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002918{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002919 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002920
Laurence Lundblade02625d42020-06-25 14:41:41 -07002921 /*
2922 First the pre-order-traversal byte offset is positioned to the
2923 item just after the bounded mode item that was just consumed.
2924 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002925 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2926
Laurence Lundblade02625d42020-06-25 14:41:41 -07002927 /*
2928 Next, set the current nesting level to one above the bounded level
2929 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002930
Laurence Lundblade02625d42020-06-25 14:41:41 -07002931 DecodeNesting_CheckBoundedType() is always called before this and
2932 makes sure pCurrentBounded is valid.
2933 */
2934 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2935
2936 /*
2937 This does the complex work of leveling up the pre-order traversal
2938 when the end of a map or array or another bounded level is
2939 reached. It may do nothing, or ascend all the way to the top
2940 level.
2941 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07002942 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002943 if(uErr != QCBOR_SUCCESS) {
2944 goto Done;
2945 }
2946
Laurence Lundblade02625d42020-06-25 14:41:41 -07002947 /*
2948 This makes the next highest bounded level the current bounded
2949 level. If there is no next highest level, then no bounded mode is
2950 in effect.
2951 */
2952 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002953
Laurence Lundblade02625d42020-06-25 14:41:41 -07002954 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002955
2956Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002957 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002958 return uErr;
2959}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002960
Laurence Lundblade02625d42020-06-25 14:41:41 -07002961
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002962// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002963void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002964{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002965 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002966 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002967 return;
2968 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002969
Laurence Lundblade02625d42020-06-25 14:41:41 -07002970 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002971
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002972 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002973 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2974 goto Done;
2975 }
2976
Laurence Lundblade02625d42020-06-25 14:41:41 -07002977 /*
2978 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002979 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002980 from previous map search, then do a dummy search.
2981 */
2982 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002983 QCBORItem Dummy;
2984 Dummy.uLabelType = QCBOR_TYPE_NONE;
2985 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2986 if(uErr != QCBOR_SUCCESS) {
2987 goto Done;
2988 }
2989 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002990
Laurence Lundblade02625d42020-06-25 14:41:41 -07002991 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002992
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002993Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002994 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002995}
2996
2997
Laurence Lundblade1341c592020-04-11 14:19:05 -07002998
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002999static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003000 const QCBORItem *pItem,
3001 uint8_t uTagRequirement,
3002 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003003{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003004 if(pBstr) {
3005 *pBstr = NULLUsefulBufC;
3006 }
3007
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003008 if(pMe->uLastError != QCBOR_SUCCESS) {
3009 // Already in error state; do nothing.
3010 return pMe->uLastError;
3011 }
3012
3013 QCBORError uError = QCBOR_SUCCESS;
3014
3015 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3016 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3017 goto Done;;
3018 }
3019
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003020 const TagSpecification TagSpec =
3021 {
3022 uTagRequirement,
3023 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3024 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3025 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003026
3027 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
3028 if(uError != QCBOR_SUCCESS) {
3029 goto Done;
3030 }
3031
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003032 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003033 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07003034 so the increment in NestLevelAscender called by ExitBoundedLevel()
3035 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003036 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003037 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003038
3039 if(pBstr) {
3040 *pBstr = pItem->val.string;
3041 }
3042
3043 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003044
3045 // Need to move UIB input cursor to the right place
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003046 // Most of these calls are simple inline accessors so this doesn't
3047 // amount to much code. There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003048 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003049 if(uEndOfBstr >= UINT32_MAX || uPreviousLength >= UINT32_MAX) {
3050 // TODO: test this error condition
3051 uError = QCBOR_ERR_BUFFER_TOO_LARGE;
3052 goto Done;
3053 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003054 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003055 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003056
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003057 // Casts are OK because of the checks above.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003058 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003059 (uint32_t)uPreviousLength,
3060 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003061Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07003062 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003063
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003064 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003065}
3066
3067
Laurence Lundblade02625d42020-06-25 14:41:41 -07003068/*
3069 Public function, see header qcbor/qcbor_decode.h file
3070 */
3071void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003072 uint8_t uTagRequirement,
3073 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003074{
3075 if(pMe->uLastError != QCBOR_SUCCESS) {
3076 // Already in error state; do nothing.
3077 return;
3078 }
3079
3080 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003081 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003082 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3083 if(pMe->uLastError != QCBOR_SUCCESS) {
3084 return;
3085 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003086
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003087 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003088 &Item,
3089 uTagRequirement,
3090 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003091}
3092
3093
Laurence Lundblade02625d42020-06-25 14:41:41 -07003094/*
3095 Public function, see header qcbor/qcbor_decode.h file
3096 */
3097void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003098 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003099 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003100 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003101{
3102 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003103 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003104
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003105 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003106}
3107
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003108
Laurence Lundblade02625d42020-06-25 14:41:41 -07003109/*
3110 Public function, see header qcbor/qcbor_decode.h file
3111 */
3112void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003113 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003114 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003115 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003116{
3117 QCBORItem Item;
3118 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3119
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003120 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003121}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003122
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003123
Laurence Lundblade02625d42020-06-25 14:41:41 -07003124/*
3125 Public function, see header qcbor/qcbor_decode.h file
3126 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003127void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003128{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003129 if(pMe->uLastError != QCBOR_SUCCESS) {
3130 // Already in error state; do nothing.
3131 return;
3132 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003133
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003134 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003135 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3136 return;
3137 }
3138
3139 /*
3140 Reset the length of the UsefulInputBuf to what it was before
3141 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003142 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003143 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3144 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003145
3146
Laurence Lundblade02625d42020-06-25 14:41:41 -07003147 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003148 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003149}
3150
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003151
Laurence Lundbladee6430642020-03-14 21:15:44 -07003152
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003153
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003154
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003155
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003156
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003157
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003158static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3159{
3160 switch(pItem->uDataType) {
3161 case QCBOR_TYPE_TRUE:
3162 *pBool = true;
3163 return QCBOR_SUCCESS;
3164 break;
3165
3166 case QCBOR_TYPE_FALSE:
3167 *pBool = false;
3168 return QCBOR_SUCCESS;
3169 break;
3170
3171 default:
3172 return QCBOR_ERR_UNEXPECTED_TYPE;
3173 break;
3174 }
3175}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003176
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003177
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003178/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003179 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003180*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003181void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003182{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003183 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003184 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003185 return;
3186 }
3187
Laurence Lundbladec4537442020-04-14 18:53:22 -07003188 QCBORError nError;
3189 QCBORItem Item;
3190
3191 nError = QCBORDecode_GetNext(pMe, &Item);
3192 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003193 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003194 return;
3195 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003196 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003197}
3198
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003199
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003200/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003201 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003202*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003203void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003204{
3205 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003206 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003207
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003208 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003209}
3210
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003211
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003212/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003213 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003214*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003215void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3216{
3217 QCBORItem Item;
3218 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3219
3220 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3221}
3222
3223
3224
Laurence Lundbladec7114722020-08-13 05:11:40 -07003225
3226
3227static void ProcessEpochDate(QCBORDecodeContext *pMe,
3228 QCBORItem *pItem,
3229 uint8_t uTagRequirement,
3230 int64_t *pnTime)
3231{
3232 if(pMe->uLastError != QCBOR_SUCCESS) {
3233 // Already in error state, do nothing
3234 return;
3235 }
3236
3237 QCBORError uErr;
3238
3239 const TagSpecification TagSpec =
3240 {
3241 uTagRequirement,
3242 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3243 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT}
3244 };
3245
Laurence Lundblade4b270642020-08-14 12:53:07 -07003246 // TODO: this will give an unexpected type error instead of
Laurence Lundbladec7114722020-08-13 05:11:40 -07003247 // overflow error for QCBOR_TYPE_UINT64 because TagSpec
3248 // only has three target types.
3249 uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
3250 if(uErr != QCBOR_SUCCESS) {
3251 goto Done;
3252 }
3253
3254 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3255 uErr = DecodeDateEpoch(pItem);
3256 if(uErr != QCBOR_SUCCESS) {
3257 goto Done;
3258 }
3259 }
3260
3261 *pnTime = pItem->val.epochDate.nSeconds;
3262
3263Done:
3264 pMe->uLastError = (uint8_t)uErr;
3265}
3266
3267
3268void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
3269 uint8_t uTagRequirement,
3270 int64_t *pnTime)
3271{
3272 if(pMe->uLastError != QCBOR_SUCCESS) {
3273 // Already in error state, do nothing
3274 return;
3275 }
3276
3277 QCBORItem Item;
3278 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3279
3280 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3281}
3282
3283
3284void
3285QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3286 int64_t nLabel,
3287 uint8_t uTagRequirement,
3288 int64_t *pnTime)
3289{
3290 QCBORItem Item;
3291 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3292 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3293}
3294
3295
3296void
3297QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3298 const char *szLabel,
3299 uint8_t uTagRequirement,
3300 int64_t *pnTime)
3301{
3302 QCBORItem Item;
3303 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3304 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3305}
3306
3307
3308
3309
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003310void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3311 TagSpecification TagSpec,
3312 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003313{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003314 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003315 // Already in error state, do nothing
3316 return;
3317 }
3318
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003319 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003320 QCBORItem Item;
3321
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003322 uError = QCBORDecode_GetNext(pMe, &Item);
3323 if(uError != QCBOR_SUCCESS) {
3324 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003325 return;
3326 }
3327
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003328 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3329
3330 if(pMe->uLastError == QCBOR_SUCCESS) {
3331 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003332 }
3333}
3334
Laurence Lundbladec4537442020-04-14 18:53:22 -07003335
3336
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003337
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003338static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003339 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003340 UsefulBufC *pValue,
3341 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003342{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003343 const TagSpecification TagSpec =
3344 {
3345 uTagRequirement,
3346 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3347 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3348 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003349
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003350 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
3351 if(uErr != QCBOR_SUCCESS) {
3352 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003353 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003354
3355 *pValue = pItem->val.string;
3356
3357 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3358 *pbIsNegative = false;
3359 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3360 *pbIsNegative = true;
3361 }
3362
3363 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003364}
3365
3366
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003367/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003368 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003369 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003370void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3371 uint8_t uTagRequirement,
3372 UsefulBufC *pValue,
3373 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003374{
3375 if(pMe->uLastError != QCBOR_SUCCESS) {
3376 // Already in error state, do nothing
3377 return;
3378 }
3379
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003380 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003381 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3382 if(uError != QCBOR_SUCCESS) {
3383 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003384 return;
3385 }
3386
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003387 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003388}
3389
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003390
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003391/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003392 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003393*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003394void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3395 int64_t nLabel,
3396 uint8_t uTagRequirement,
3397 UsefulBufC *pValue,
3398 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003399{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003400 QCBORItem Item;
3401 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003402 if(pMe->uLastError != QCBOR_SUCCESS) {
3403 return;
3404 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003405
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003406 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003407}
3408
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003409
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003410/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003411 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003412*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003413void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3414 const char *szLabel,
3415 uint8_t uTagRequirement,
3416 UsefulBufC *pValue,
3417 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003418{
3419 QCBORItem Item;
3420 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003421 if(pMe->uLastError != QCBOR_SUCCESS) {
3422 return;
3423 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003424
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003425 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003426}
3427
3428
3429
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003430
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003431// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003432QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3433 const QCBORItem *pItem,
3434 UsefulBufC *pMessage,
3435 bool *pbIsNot7Bit)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003436{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003437 const TagSpecification TagSpecText =
3438 {
3439 uTagRequirement,
3440 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3441 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3442 };
3443 const TagSpecification TagSpecBinary =
3444 {
3445 uTagRequirement,
3446 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3447 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3448 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003449
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003450 QCBORError uReturn;
3451
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003452 if(CheckTagRequirement(TagSpecText, pItem->uDataType) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003453 *pMessage = pItem->val.string;
3454 if(pbIsNot7Bit != NULL) {
3455 *pbIsNot7Bit = false;
3456 }
3457 uReturn = QCBOR_SUCCESS;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003458 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003459 *pMessage = pItem->val.string;
3460 if(pbIsNot7Bit != NULL) {
3461 *pbIsNot7Bit = true;
3462 }
3463 uReturn = QCBOR_SUCCESS;
3464
3465 } else {
3466 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3467 }
3468
3469 return uReturn;
3470}
3471
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003472// Improvement: add methods for wrapped CBOR, a simple alternate to EnterBstrWrapped
3473
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003474
3475
3476
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003477#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003478
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003479typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003480
3481
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003482// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003483static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003484{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003485 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003486
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003487 if(uResult != 0) {
3488 /* This loop will run a maximum of 19 times because
3489 * UINT64_MAX < 10 ^^ 19. More than that will cause
3490 * exit with the overflow error
3491 */
3492 for(; nExponent > 0; nExponent--) {
3493 if(uResult > UINT64_MAX / 10) {
3494 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3495 }
3496 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003497 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003498
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003499 for(; nExponent < 0; nExponent++) {
3500 uResult = uResult / 10;
3501 if(uResult == 0) {
3502 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3503 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003504 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003505 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003506 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003507
3508 *puResult = uResult;
3509
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003510 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003511}
3512
3513
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003514// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003515static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003516{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003517 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003518
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003519 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003520
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003521 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003522 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003523 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003524 */
3525 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003526 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003527 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003528 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003529 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003530 nExponent--;
3531 }
3532
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003533 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003534 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003535 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3536 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003537 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003538 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003539 }
3540
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003541 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003542
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003543 return QCBOR_SUCCESS;
3544}
3545
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003546
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003547/*
3548 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3549 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003550static inline QCBORError ExponentiateNN(int64_t nMantissa,
3551 int64_t nExponent,
3552 int64_t *pnResult,
3553 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003554{
3555 uint64_t uResult;
3556
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003557 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003558 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003559 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3560
3561 // Do the exponentiation of the positive mantissa
3562 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3563 if(uReturn) {
3564 return uReturn;
3565 }
3566
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003567
Laurence Lundblade983500d2020-05-14 11:49:34 -07003568 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3569 of INT64_MIN. This assumes two's compliment representation where
3570 INT64_MIN is one increment farther from 0 than INT64_MAX.
3571 Trying to write -INT64_MIN doesn't work to get this because the
3572 compiler tries to work with an int64_t which can't represent
3573 -INT64_MIN.
3574 */
3575 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3576
3577 // Error out if too large
3578 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003579 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3580 }
3581
3582 // Casts are safe because of checks above
3583 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3584
3585 return QCBOR_SUCCESS;
3586}
3587
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003588
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003589/*
3590 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3591 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003592static inline QCBORError ExponentitateNU(int64_t nMantissa,
3593 int64_t nExponent,
3594 uint64_t *puResult,
3595 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003596{
3597 if(nMantissa < 0) {
3598 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3599 }
3600
3601 // Cast to unsigned is OK because of check for negative
3602 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3603 // Exponentiation is straight forward
3604 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3605}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003606
3607
3608/*
3609 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3610 */
3611static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3612 int64_t nExponent,
3613 uint64_t *puResult,
3614 fExponentiator pfExp)
3615{
3616 return (*pfExp)(uMantissa, nExponent, puResult);
3617}
3618
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003619#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3620
3621
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003622
3623
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003624
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003625static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003626{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003627 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003628
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003629 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003630 const uint8_t *pByte = BigNum.ptr;
3631 size_t uLen = BigNum.len;
3632 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003633 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003634 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003635 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003636 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003637 }
3638
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003639 *pResult = uResult;
3640 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003641}
3642
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003643
Laurence Lundblade887add82020-05-17 05:50:34 -07003644static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003645{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003646 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003647}
3648
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003649
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003650static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003651{
3652 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003653 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3654 if(uError) {
3655 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003656 }
3657 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3658 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003659 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003660}
3661
3662
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003663static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003664{
3665 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003666 /* The negative integer furthest from zero for a C int64_t is
3667 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3668 negative number in CBOR is computed as -n - 1 where n is the
3669 encoded integer, where n is what is in the variable BigNum. When
3670 converting BigNum to a uint64_t, the maximum value is thus
3671 INT64_MAX, so that when it -n - 1 is applied to it the result will
3672 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003673
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003674 -n - 1 <= INT64_MIN.
3675 -n - 1 <= -INT64_MAX - 1
3676 n <= INT64_MAX.
3677 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003678 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003679 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003680 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003681 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003682
3683 /// Now apply -n - 1. The cast is safe because
3684 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3685 // is the largest positive integer that an int64_t can
3686 // represent. */
3687 *pnResult = -(int64_t)uResult - 1;
3688
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003689 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003690}
3691
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003692
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003693
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003694
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003695#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003696
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003697
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003698/*
3699Convert a integers and floats to an int64_t.
3700
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003701\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003702
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003703\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003704
3705\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3706
3707\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3708
3709*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003710static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003711{
3712 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003713 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003714 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003715#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003716 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003717 // TODO: what about under/overflow here?
3718 // Invokes the floating-point HW and/or compiler-added libraries
3719 feclearexcept(FE_ALL_EXCEPT);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003720 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3721 *pnValue = llround(pItem->val.dfnum);
3722 } else {
3723 *pnValue = lroundf(pItem->val.fnum);
3724 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003725 if(fetestexcept(FE_INVALID)) {
3726 // TODO: better error code
3727 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3728 }
3729 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003730 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003731 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003732#else
3733 return QCBOR_ERR_HW_FLOAT_DISABLED;
3734#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003735 break;
3736
3737 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003738 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003739 *pnValue = pItem->val.int64;
3740 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003741 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003742 }
3743 break;
3744
3745 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003746 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003747 if(pItem->val.uint64 < INT64_MAX) {
3748 *pnValue = pItem->val.int64;
3749 } else {
3750 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3751 }
3752 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003753 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003754 }
3755 break;
3756
3757 default:
3758 return QCBOR_ERR_UNEXPECTED_TYPE;
3759 }
3760 return QCBOR_SUCCESS;
3761}
3762
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003763
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003764void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003765 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003766 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003767 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003768{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003769 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003770 return;
3771 }
3772
Laurence Lundbladee6430642020-03-14 21:15:44 -07003773 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003774 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3775 if(uError) {
3776 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003777 return;
3778 }
3779
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003780 if(pItem) {
3781 *pItem = Item;
3782 }
3783
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003784 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003785}
3786
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003787
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003788void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3789 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003790 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003791 int64_t *pnValue,
3792 QCBORItem *pItem)
3793{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003794 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003795 if(pMe->uLastError != QCBOR_SUCCESS) {
3796 return;
3797 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003798
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003799 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003800}
3801
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003802
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003803void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3804 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003805 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003806 int64_t *pnValue,
3807 QCBORItem *pItem)
3808{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003809 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003810 if(pMe->uLastError != QCBOR_SUCCESS) {
3811 return;
3812 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003813
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003814 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003815}
3816
3817
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003818/*
3819 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003820
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003821 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003822
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003823 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003824
3825 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3826
3827 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3828
3829 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003830static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003831{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003832 switch(pItem->uDataType) {
3833
3834 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003835 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003836 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003837 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003838 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003839 }
3840 break;
3841
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003842 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003843 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003844 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003845 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003846 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003847 }
3848 break;
3849
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003850#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3851 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003852 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003853 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003854 pItem->val.expAndMantissa.nExponent,
3855 pnValue,
3856 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003857 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003858 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003859 }
3860 break;
3861
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003862 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003863 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003864 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003865 pItem->val.expAndMantissa.nExponent,
3866 pnValue,
3867 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003868 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003869 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003870 }
3871 break;
3872
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003873 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003874 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003875 int64_t nMantissa;
3876 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003877 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3878 if(uErr) {
3879 return uErr;
3880 }
3881 return ExponentiateNN(nMantissa,
3882 pItem->val.expAndMantissa.nExponent,
3883 pnValue,
3884 Exponentitate10);
3885 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003886 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003887 }
3888 break;
3889
3890 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003891 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003892 int64_t nMantissa;
3893 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003894 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3895 if(uErr) {
3896 return uErr;
3897 }
3898 return ExponentiateNN(nMantissa,
3899 pItem->val.expAndMantissa.nExponent,
3900 pnValue,
3901 Exponentitate10);
3902 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003903 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003904 }
3905 break;
3906
3907 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003908 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003909 int64_t nMantissa;
3910 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003911 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3912 if(uErr) {
3913 return uErr;
3914 }
3915 return ExponentiateNN(nMantissa,
3916 pItem->val.expAndMantissa.nExponent,
3917 pnValue,
3918 Exponentitate2);
3919 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003920 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003921 }
3922 break;
3923
3924 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003925 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003926 int64_t nMantissa;
3927 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003928 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3929 if(uErr) {
3930 return uErr;
3931 }
3932 return ExponentiateNN(nMantissa,
3933 pItem->val.expAndMantissa.nExponent,
3934 pnValue,
3935 Exponentitate2);
3936 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003937 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003938 }
3939 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003940#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3941
Laurence Lundbladee6430642020-03-14 21:15:44 -07003942
Laurence Lundbladec4537442020-04-14 18:53:22 -07003943 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003944 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003945}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003946
3947
Laurence Lundbladec4537442020-04-14 18:53:22 -07003948/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003949 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003950 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003951void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003952{
3953 QCBORItem Item;
3954
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003955 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003956
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003957 if(pMe->uLastError == QCBOR_SUCCESS) {
3958 // The above conversion succeeded
3959 return;
3960 }
3961
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003962 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003963 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003964 return;
3965 }
3966
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003967 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003968}
3969
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003970
3971/*
3972Public function, see header qcbor/qcbor_decode.h file
3973*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003974void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
3975 int64_t nLabel,
3976 uint32_t uConvertTypes,
3977 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003978{
3979 QCBORItem Item;
3980
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003981 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003982
3983 if(pMe->uLastError == QCBOR_SUCCESS) {
3984 // The above conversion succeeded
3985 return;
3986 }
3987
3988 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3989 // The above conversion failed in a way that code below can't correct
3990 return;
3991 }
3992
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003993 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003994}
3995
3996
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003997/*
3998Public function, see header qcbor/qcbor_decode.h file
3999*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004000void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4001 const char *szLabel,
4002 uint32_t uConvertTypes,
4003 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004004{
4005 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004006 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004007
4008 if(pMe->uLastError == QCBOR_SUCCESS) {
4009 // The above conversion succeeded
4010 return;
4011 }
4012
4013 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4014 // The above conversion failed in a way that code below can't correct
4015 return;
4016 }
4017
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004018 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004019}
4020
4021
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004022static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004023{
4024 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004025 case QCBOR_TYPE_DOUBLE:
4026 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004027#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004028 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4029 // TODO: this code needs work
4030 feclearexcept(FE_ALL_EXCEPT);
4031 double dRounded = round(pItem->val.dfnum);
4032 // TODO: over/underflow
4033 if(fetestexcept(FE_INVALID)) {
4034 // TODO: better error code
4035 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4036 } else if(isnan(dRounded)) {
4037 // TODO: better error code
4038 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4039 } else if(dRounded >= 0) {
4040 *puValue = (uint64_t)dRounded;
4041 } else {
4042 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4043 }
4044 } else {
4045 return QCBOR_ERR_UNEXPECTED_TYPE;
4046 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004047#else
4048 return QCBOR_ERR_HW_FLOAT_DISABLED;
4049#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004050 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004051
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004052 case QCBOR_TYPE_INT64:
4053 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4054 if(pItem->val.int64 >= 0) {
4055 *puValue = (uint64_t)pItem->val.int64;
4056 } else {
4057 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4058 }
4059 } else {
4060 return QCBOR_ERR_UNEXPECTED_TYPE;
4061 }
4062 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004063
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004064 case QCBOR_TYPE_UINT64:
4065 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4066 *puValue = pItem->val.uint64;
4067 } else {
4068 return QCBOR_ERR_UNEXPECTED_TYPE;
4069 }
4070 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004071
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004072 default:
4073 return QCBOR_ERR_UNEXPECTED_TYPE;
4074 }
4075
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004076 return QCBOR_SUCCESS;
4077}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004078
4079
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004080void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004081 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004082 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004083 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004084{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004085 if(pMe->uLastError != QCBOR_SUCCESS) {
4086 return;
4087 }
4088
Laurence Lundbladec4537442020-04-14 18:53:22 -07004089 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004090
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004091 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4092 if(uError) {
4093 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004094 return;
4095 }
4096
Laurence Lundbladea826c502020-05-10 21:07:00 -07004097 if(pItem) {
4098 *pItem = Item;
4099 }
4100
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004101 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004102}
4103
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004104
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004105void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4106 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004107 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004108 uint64_t *puValue,
4109 QCBORItem *pItem)
4110{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004111 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004112 if(pMe->uLastError != QCBOR_SUCCESS) {
4113 return;
4114 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004115
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004116 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004117}
4118
4119
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004120void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004121 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004122 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004123 uint64_t *puValue,
4124 QCBORItem *pItem)
4125{
4126 if(pMe->uLastError != QCBOR_SUCCESS) {
4127 return;
4128 }
4129
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004130 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004131 if(pMe->uLastError != QCBOR_SUCCESS) {
4132 return;
4133 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004134
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004135 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004136}
4137
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004138
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004139/*
4140 Public function, see header qcbor/qcbor_decode.h file
4141*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004142static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004143{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004144 switch(pItem->uDataType) {
4145
4146 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004147 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004148 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4149 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004150 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004151 }
4152 break;
4153
4154 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004155 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004156 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4157 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004158 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004159 }
4160 break;
4161
4162#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4163
4164 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004165 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004166 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004167 pItem->val.expAndMantissa.nExponent,
4168 puValue,
4169 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004170 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004171 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004172 }
4173 break;
4174
4175 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004176 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004177 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4178 pItem->val.expAndMantissa.nExponent,
4179 puValue,
4180 Exponentitate2);
4181 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004182 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004183 }
4184 break;
4185
4186 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004187 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004188 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004189 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004190 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004191 if(uErr != QCBOR_SUCCESS) {
4192 return uErr;
4193 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004194 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004195 pItem->val.expAndMantissa.nExponent,
4196 puValue,
4197 Exponentitate10);
4198 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004199 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004200 }
4201 break;
4202
4203 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004204 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004205 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4206 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004207 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004208 }
4209 break;
4210
4211 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004212 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004213 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004214 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004215 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004216 if(uErr != QCBOR_SUCCESS) {
4217 return uErr;
4218 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004219 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004220 pItem->val.expAndMantissa.nExponent,
4221 puValue,
4222 Exponentitate2);
4223 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004224 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004225 }
4226 break;
4227
4228 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004229 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004230 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4231 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004232 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004233 }
4234 break;
4235#endif
4236 default:
4237 return QCBOR_ERR_UNEXPECTED_TYPE;
4238 }
4239}
4240
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004241
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004242/*
4243 Public function, see header qcbor/qcbor_decode.h file
4244*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004245void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004246{
4247 QCBORItem Item;
4248
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004249 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004250
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004251 if(pMe->uLastError == QCBOR_SUCCESS) {
4252 // The above conversion succeeded
4253 return;
4254 }
4255
4256 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4257 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004258 return;
4259 }
4260
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004261 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004262}
4263
Laurence Lundbladec4537442020-04-14 18:53:22 -07004264
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004265/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004266 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004267*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004268void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004269{
4270 QCBORItem Item;
4271
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004272 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004273
4274 if(pMe->uLastError == QCBOR_SUCCESS) {
4275 // The above conversion succeeded
4276 return;
4277 }
4278
4279 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4280 // The above conversion failed in a way that code below can't correct
4281 return;
4282 }
4283
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004284 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004285}
4286
4287
4288/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004289 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004290*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004291void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004292{
4293 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004294 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004295
4296 if(pMe->uLastError == QCBOR_SUCCESS) {
4297 // The above conversion succeeded
4298 return;
4299 }
4300
4301 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4302 // The above conversion failed in a way that code below can't correct
4303 return;
4304 }
4305
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004306 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004307}
4308
4309
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004310static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004311{
4312 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004313 case QCBOR_TYPE_FLOAT:
4314#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4315 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4316 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4317 *pdValue = (double)pItem->val.fnum;
4318 } else {
4319 return QCBOR_ERR_UNEXPECTED_TYPE;
4320 }
4321 }
4322#else
4323 return QCBOR_ERR_HW_FLOAT_DISABLED;
4324#endif
4325 break;
4326
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004327 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004328 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4329 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004330 *pdValue = pItem->val.dfnum;
4331 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004332 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004333 }
4334 }
4335 break;
4336
4337 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004338#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004339 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004340 // TODO: how does this work?
4341 *pdValue = (double)pItem->val.int64;
4342
4343 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004344 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004345 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004346#else
4347 return QCBOR_ERR_HW_FLOAT_DISABLED;
4348#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004349 break;
4350
4351 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004352#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004353 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004354 *pdValue = (double)pItem->val.uint64;
4355 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004356 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004357 }
4358 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004359#else
4360 return QCBOR_ERR_HW_FLOAT_DISABLED;
4361#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004362
4363 default:
4364 return QCBOR_ERR_UNEXPECTED_TYPE;
4365 }
4366
4367 return QCBOR_SUCCESS;
4368}
4369
4370
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004371void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004372 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004373 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004374 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004375{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004376 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004377 return;
4378 }
4379
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004380 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004381
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004382 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004383 if(uError) {
4384 pMe->uLastError = (uint8_t)uError;
4385 return;
4386 }
4387
4388 if(pItem) {
4389 *pItem = Item;
4390 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004391
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004392 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004393}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004394
Laurence Lundbladec4537442020-04-14 18:53:22 -07004395
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004396void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4397 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004398 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004399 double *pdValue,
4400 QCBORItem *pItem)
4401{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004402 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004403 if(pMe->uLastError != QCBOR_SUCCESS) {
4404 return;
4405 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004406
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004407 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004408}
4409
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004410
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004411void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4412 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004413 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004414 double *pdValue,
4415 QCBORItem *pItem)
4416{
4417 if(pMe->uLastError != QCBOR_SUCCESS) {
4418 return;
4419 }
4420
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004421 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004422 if(pMe->uLastError != QCBOR_SUCCESS) {
4423 return;
4424 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004425
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004426 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004427}
4428
4429
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004430#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004431static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4432{
4433 double dResult;
4434
4435 dResult = 0.0;
4436 const uint8_t *pByte = BigNum.ptr;
4437 size_t uLen = BigNum.len;
4438 /* This will overflow and become the float value INFINITY if the number
4439 is too large to fit. No error will be logged.
4440 TODO: should an error be logged? */
4441 while(uLen--) {
4442 dResult = (dResult * 256.0) + (double)*pByte++;
4443 }
4444
4445 return dResult;
4446}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004447#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4448
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004449
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004450static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004451{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004452#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004453 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004454 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4455
4456 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004457 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004458
4459#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004460 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004461 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004462 // TODO: rounding and overflow errors
4463 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4464 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
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:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004471 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004472 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4473 exp2((double)pItem->val.expAndMantissa.nExponent);
4474 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004475 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004476 }
4477 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004478#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004479
4480 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004481 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004482 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4483 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004484 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004485 }
4486 break;
4487
4488 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004489 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004490 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004491 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004492 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004493 }
4494 break;
4495
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004496#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004497 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004498 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004499 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4500 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4501 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004502 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004503 }
4504 break;
4505
4506 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004507 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004508 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4509 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4510 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004511 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004512 }
4513 break;
4514
4515 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004516 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004517 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4518 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4519 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004520 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004521 }
4522 break;
4523
4524 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004525 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004526 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004527 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4528 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004529 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004530 }
4531 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004532#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4533
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004534
4535 default:
4536 return QCBOR_ERR_UNEXPECTED_TYPE;
4537 }
4538
4539 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004540
4541#else
4542 (void)pItem;
4543 (void)uConvertTypes;
4544 (void)pdValue;
4545 return QCBOR_ERR_HW_FLOAT_DISABLED;
4546#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4547
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004548}
4549
4550
4551/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004552 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004553*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004554void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004555{
4556
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004557 QCBORItem Item;
4558
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004559 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -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)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004572}
4573
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004574
4575/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004576 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004577*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004578void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004579{
4580 QCBORItem Item;
4581
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004582 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004583
4584 if(pMe->uLastError == QCBOR_SUCCESS) {
4585 // The above conversion succeeded
4586 return;
4587 }
4588
4589 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4590 // The above conversion failed in a way that code below can't correct
4591 return;
4592 }
4593
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004594 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004595}
4596
4597
4598/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004599 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004600*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004601void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004602{
4603 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004604 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004605
4606 if(pMe->uLastError == QCBOR_SUCCESS) {
4607 // The above conversion succeeded
4608 return;
4609 }
4610
4611 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4612 // The above conversion failed in a way that code below can't correct
4613 return;
4614 }
4615
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004616 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004617}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004618
4619
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004620
4621
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004622#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004623static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4624{
4625 while((uInt & 0xff00000000000000UL) == 0) {
4626 uInt = uInt << 8;
4627 };
4628
4629 UsefulOutBuf UOB;
4630
4631 UsefulOutBuf_Init(&UOB, Buffer);
4632
4633 while(uInt) {
4634 const uint64_t xx = uInt & 0xff00000000000000UL;
4635 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4636 uInt = uInt << 8;
4637 (void)xx;
4638 }
4639
4640 return UsefulOutBuf_OutUBuf(&UOB);
4641}
4642
4643
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004644static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4645 TagSpecification TagSpec,
4646 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004647{
4648 QCBORError uErr;
4649 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004650 while(1) {
4651 uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
4652 if(uErr != QCBOR_SUCCESS) {
4653 goto Done;
4654 }
4655
4656 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4657 break; // Successful exit. Moving on to finish decoding.
4658 }
4659
4660 // The item is an array, which means an undecoded
4661 // mantissa and exponent, so decode it. It will then
4662 // have a different type and exit the loop if.
4663 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4664 if(uErr != QCBOR_SUCCESS) {
4665 goto Done;
4666 }
4667
4668 // Second time around, the type must match.
4669 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_MATCH_TAG;
4670 }
4671Done:
4672 return uErr;
4673}
4674
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004675
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004676static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004677 TagSpecification TagSpec,
4678 QCBORItem *pItem,
4679 int64_t *pnMantissa,
4680 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004681{
4682 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004683
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004684 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004685 if(uErr != QCBOR_SUCCESS) {
4686 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004687 }
4688
4689 switch (pItem->uDataType) {
4690
4691 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004692 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004693 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4694 *pnExponent = pItem->val.expAndMantissa.nExponent;
4695 break;
4696
4697 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004698 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004699 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004700 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004701 break;
4702
4703 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004704 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004705 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004706 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004707 break;
4708
4709 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004710 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004711 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004712
4713 Done:
4714 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004715}
4716
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004717
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004718static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004719 TagSpecification TagSpec,
4720 QCBORItem *pItem,
4721 UsefulBuf BufferForMantissa,
4722 UsefulBufC *pMantissa,
4723 bool *pbIsNegative,
4724 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004725{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004726 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004727
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004728 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004729 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004730 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004731 }
4732
4733 uint64_t uMantissa;
4734
4735 switch (pItem->uDataType) {
4736
4737 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004738 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004739 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
4740 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
4741 *pbIsNegative = false;
4742 } else {
4743 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
4744 *pbIsNegative = true;
4745 }
4746 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
4747 *pnExponent = pItem->val.expAndMantissa.nExponent;
4748 break;
4749
4750 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004751 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004752 *pnExponent = pItem->val.expAndMantissa.nExponent;
4753 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4754 *pbIsNegative = false;
4755 break;
4756
4757 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004758 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004759 *pnExponent = pItem->val.expAndMantissa.nExponent;
4760 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4761 *pbIsNegative = true;
4762 break;
4763
4764 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004765 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004766 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004767
4768Done:
4769 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004770}
4771
4772
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004773/*
4774 Public function, see header qcbor/qcbor_decode.h file
4775*/
4776void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
4777 uint8_t uTagRequirement,
4778 int64_t *pnMantissa,
4779 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004780{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004781 if(pMe->uLastError != QCBOR_SUCCESS) {
4782 return;
4783 }
4784
4785 QCBORItem Item;
4786 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4787 if(uError) {
4788 pMe->uLastError = (uint8_t)uError;
4789 return;
4790 }
4791
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004792 const TagSpecification TagSpec =
4793 {
4794 uTagRequirement,
4795 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4796 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4797 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004798
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004799 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004800}
4801
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004802
4803/*
4804 Public function, see header qcbor/qcbor_decode.h file
4805*/
4806void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004807 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004808 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004809 int64_t *pnMantissa,
4810 int64_t *pnExponent)
4811{
4812 if(pMe->uLastError != QCBOR_SUCCESS) {
4813 return;
4814 }
4815
4816 QCBORItem Item;
4817 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4818
4819 const TagSpecification TagSpec =
4820 {
4821 uTagRequirement,
4822 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4823 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4824 };
4825
4826 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4827}
4828
4829
4830/*
4831 Public function, see header qcbor/qcbor_decode.h file
4832*/
4833void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004834 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004835 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004836 int64_t *pnMantissa,
4837 int64_t *pnExponent)
4838{
4839 if(pMe->uLastError != QCBOR_SUCCESS) {
4840 return;
4841 }
4842
4843 QCBORItem Item;
4844 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4845
4846 const TagSpecification TagSpec =
4847 {
4848 uTagRequirement,
4849 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4850 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4851 };
4852
4853 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4854}
4855
4856
4857/*
4858 Public function, see header qcbor/qcbor_decode.h file
4859*/
4860void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
4861 uint8_t uTagRequirement,
4862 UsefulBuf MantissaBuffer,
4863 UsefulBufC *pMantissa,
4864 bool *pbMantissaIsNegative,
4865 int64_t *pnExponent)
4866{
4867 if(pMe->uLastError != QCBOR_SUCCESS) {
4868 return;
4869 }
4870
4871 QCBORItem Item;
4872 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4873 if(uError) {
4874 pMe->uLastError = (uint8_t)uError;
4875 return;
4876 }
4877
4878 const TagSpecification TagSpec =
4879 {
4880 uTagRequirement,
4881 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4882 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4883 };
4884
4885 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
4886}
4887
4888
4889/*
4890 Public function, see header qcbor/qcbor_decode.h file
4891*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004892void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004893 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004894 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004895 UsefulBuf BufferForMantissa,
4896 UsefulBufC *pMantissa,
4897 bool *pbIsNegative,
4898 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004899{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004900 if(pMe->uLastError != QCBOR_SUCCESS) {
4901 return;
4902 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004903
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004904 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004905 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004906 if(pMe->uLastError != QCBOR_SUCCESS) {
4907 return;
4908 }
4909
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004910 const TagSpecification TagSpec =
4911 {
4912 uTagRequirement,
4913 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4914 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4915 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004916
4917 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004918}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004919
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004920
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004921/*
4922 Public function, see header qcbor/qcbor_decode.h file
4923*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004924void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004925 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004926 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004927 UsefulBuf BufferForMantissa,
4928 UsefulBufC *pMantissa,
4929 bool *pbIsNegative,
4930 int64_t *pnExponent)
4931{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004932 if(pMe->uLastError != QCBOR_SUCCESS) {
4933 return;
4934 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004935
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004936 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004937 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4938 if(pMe->uLastError != QCBOR_SUCCESS) {
4939 return;
4940 }
4941
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004942 const TagSpecification TagSpec =
4943 {
4944 uTagRequirement,
4945 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4946 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4947 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004948
4949 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
4950}
4951
4952
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004953/*
4954 Public function, see header qcbor/qcbor_decode.h file
4955*/
4956void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
4957 uint8_t uTagRequirement,
4958 int64_t *pnMantissa,
4959 int64_t *pnExponent)
4960{
4961 if(pMe->uLastError != QCBOR_SUCCESS) {
4962 return;
4963 }
4964
4965 QCBORItem Item;
4966 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4967 if(uError) {
4968 pMe->uLastError = (uint8_t)uError;
4969 return;
4970 }
4971 const TagSpecification TagSpec =
4972 {
4973 uTagRequirement,
4974 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4975 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4976 };
4977
4978 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4979}
4980
4981
4982/*
4983 Public function, see header qcbor/qcbor_decode.h file
4984*/
4985void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004986 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004987 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004988 int64_t *pnMantissa,
4989 int64_t *pnExponent)
4990{
4991 if(pMe->uLastError != QCBOR_SUCCESS) {
4992 return;
4993 }
4994
4995 QCBORItem Item;
4996 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4997 if(pMe->uLastError != QCBOR_SUCCESS) {
4998 return;
4999 }
5000
5001 const TagSpecification TagSpec =
5002 {
5003 uTagRequirement,
5004 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5005 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5006 };
5007
5008 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5009}
5010
5011
5012/*
5013 Public function, see header qcbor/qcbor_decode.h file
5014*/
5015void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005016 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005017 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005018 int64_t *pnMantissa,
5019 int64_t *pnExponent)
5020{
5021 if(pMe->uLastError != QCBOR_SUCCESS) {
5022 return;
5023 }
5024
5025 QCBORItem Item;
5026 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5027 if(pMe->uLastError != QCBOR_SUCCESS) {
5028 return;
5029 }
5030
5031 const TagSpecification TagSpec =
5032 {
5033 uTagRequirement,
5034 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5035 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5036 };
5037
5038 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5039}
5040
5041
5042/*
5043 Public function, see header qcbor/qcbor_decode.h file
5044*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005045void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5046 uint8_t uTagRequirement,
5047 UsefulBuf MantissaBuffer,
5048 UsefulBufC *pMantissa,
5049 bool *pbMantissaIsNegative,
5050 int64_t *pnExponent)
5051{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005052 if(pMe->uLastError != QCBOR_SUCCESS) {
5053 return;
5054 }
5055
5056 QCBORItem Item;
5057 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5058 if(uError) {
5059 pMe->uLastError = (uint8_t)uError;
5060 return;
5061 }
5062
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005063 const TagSpecification TagSpec =
5064 {
5065 uTagRequirement,
5066 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5067 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5068 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005069
5070 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005071}
5072
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005073
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005074/*
5075 Public function, see header qcbor/qcbor_decode.h file
5076*/
5077void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005078 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005079 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005080 UsefulBuf BufferForMantissa,
5081 UsefulBufC *pMantissa,
5082 bool *pbIsNegative,
5083 int64_t *pnExponent)
5084{
5085 if(pMe->uLastError != QCBOR_SUCCESS) {
5086 return;
5087 }
5088
5089 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005090 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5091 if(pMe->uLastError != QCBOR_SUCCESS) {
5092 return;
5093 }
5094
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005095 const TagSpecification TagSpec =
5096 {
5097 uTagRequirement,
5098 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5099 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5100 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005101
5102 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5103}
5104
5105
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005106/*
5107 Public function, see header qcbor/qcbor_decode.h file
5108*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005109void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005110 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005111 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005112 UsefulBuf BufferForMantissa,
5113 UsefulBufC *pMantissa,
5114 bool *pbIsNegative,
5115 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005116{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005117 if(pMe->uLastError != QCBOR_SUCCESS) {
5118 return;
5119 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005120
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005121 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005122 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5123 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005124 return;
5125 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005126
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005127 const TagSpecification TagSpec =
5128 {
5129 uTagRequirement,
5130 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5131 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5132 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005133
5134 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005135}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005136
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005137#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */