blob: d9ab84092a4999736fd5d071cd31383aeaa03e22 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070035#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundbladec7114722020-08-13 05:11:40 -070036#include "ieee754.h" // Does not use math.h
37
38#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -070039#include <math.h> // For isnan(), llround(), llroudf(), round(), roundf() TODO: list
40#include <fenv.h> // feclearexcept(), fetestexcept()
Laurence Lundbladec7114722020-08-13 05:11:40 -070041#endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070042
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070043
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053044/*
45 This casts away the const-ness of a pointer, usually so it can be
46 freed or realloced.
47 */
48#define UNCONST_POINTER(ptr) ((void *)(ptr))
49
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070050
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070051
Laurence Lundblade02625d42020-06-25 14:41:41 -070052inline static bool
53// TODO: add more tests for QCBOR_TYPE_MAP_AS_ARRAY mode in qcbor_decode_tests.c
54QCBORItem_IsMapOrArray(const QCBORItem *pMe)
55{
56 const uint8_t uDataType = pMe->uDataType;
57 return uDataType == QCBOR_TYPE_MAP ||
58 uDataType == QCBOR_TYPE_ARRAY ||
59 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
60}
61
62inline static bool
63QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
64{
65 if(!QCBORItem_IsMapOrArray(pMe)){
66 return false;
67 }
68
69 if(pMe->val.uCount != 0) {
70 return false;
71 }
72 return true;
73}
74
75inline static bool
76QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
77{
78 if(!QCBORItem_IsMapOrArray(pMe)){
79 return false;
80 }
81
82 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
83 return false;
84 }
85 return true;
86}
87
88
Laurence Lundbladeee851742020-01-08 08:37:05 -080089/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070090 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080091 ===========================================================================*/
92
Laurence Lundblade9c905e82020-04-25 11:31:38 -070093/*
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070094 See commecnts about and typedef of QCBORDecodeNesting in qcbor_private.h, the data structure
95 all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -070096
Laurence Lundblade9c905e82020-04-25 11:31:38 -070097
Laurence Lundblade9c905e82020-04-25 11:31:38 -070098
Laurence Lundblade9c905e82020-04-25 11:31:38 -070099 */
100
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700101
102inline static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700103DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700104{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700105 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700106 /*
107 Limit in DecodeNesting_Descend against more than
108 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
109 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700110 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700111}
112
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700113
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700114inline static uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700115DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700116{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700117 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700118 /*
119 Limit in DecodeNesting_Descend against more than
120 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
121 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700122 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700123}
124
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700125
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700126static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700127DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700128{
129 return pNesting->pCurrentBounded->u.ma.uStartOffset;
130}
131
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700132
Laurence Lundblade085d7952020-07-24 10:26:30 -0700133static inline bool
134DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
135{
136 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
137 return true;
138 } else {
139 return false;
140 }
141}
142
143
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700144inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700145DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700146{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700147 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700148 return true;
149 } else {
150 return false;
151 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700152}
153
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700154
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700155inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700156DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700157{
158 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700159 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700160 return false;
161 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700162 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700163 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700164 return false;
165 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700166 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700167 return true;
168}
169
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700170
Laurence Lundblade642282a2020-06-23 12:00:33 -0700171inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700172DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700173{
174 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700175 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700176 return true;
177 }
178 return false;
179}
180
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700181
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700182inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700183{
184 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
185 return true;
186 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700187 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700188 return true;
189 }
190 return false;
191}
192
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700193
Laurence Lundblade085d7952020-07-24 10:26:30 -0700194inline static void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700195{
196 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700197 /*
198 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
199 larger than DecodeNesting_EnterBoundedMode which keeps it less than
200 uin32_t so the cast is safe.
201 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700202 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700203
204 if(bIsEmpty) {
205 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
206 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700207}
208
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700209
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700210inline static void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700211{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700212 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700213}
214
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700215
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700216inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700217DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700218{
219 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700220 // No bounded map or array or... set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700221 return false;
222 }
223 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700224 // Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700225 return false;
226 }
227 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700228 // Not at a bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700229 return false;
230 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700231 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700232 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700233 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700234 return false;
235 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700236 // All checks passed, got to the end of a map/array
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700237 return true;
238}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700239
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700240
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700241inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700242DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700243{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700244 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700245 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
246 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700247 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700248 return false;
249 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700250}
251
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700252
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700253inline static bool
254DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700255{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700256 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
257 return true;
258 } else {
259 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700260 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700261}
262
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700263
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700264inline static bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700265DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700266{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700267 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700268 return false;
269 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700270
271 if(pNesting->pCurrentBounded->uLevelType != uType) {
272 return false;
273 }
274
275 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700276}
277
Laurence Lundblade02625d42020-06-25 14:41:41 -0700278
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700279inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700280DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700281{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700282 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700283 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700284}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700285
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700286
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700287inline static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700288DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
289{
290 // Only call on a defnite length array / map
291 pNesting->pCurrent->u.ma.uCountCursor++;
292}
293
294
295inline static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700296DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
297{
298 pNesting->pCurrent--;
299}
300
Laurence Lundblade02625d42020-06-25 14:41:41 -0700301
302static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700303DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700304{
305 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700306 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700307 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
308 }
309
310 // The actual descend
311 pNesting->pCurrent++;
312
313 pNesting->pCurrent->uLevelType = uType;
314
315 return QCBOR_SUCCESS;
316}
317
318
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700319inline static QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700320DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700321{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700322 /*
323 Should only be called on map/array.
324
325 Have descended into this before this is called. The job here is
326 just to mark it in bounded mode.
327 */
Laurence Lundblade287b25c2020-08-06 13:48:42 -0700328 if(uOffset >= QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700329 return QCBOR_ERR_BUFFER_TOO_LARGE;
330 }
331
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700332 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700333
334 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700335
336 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700337}
338
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700339
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700340inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700341DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700342 uint8_t uQCBORType,
343 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700344{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700345 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700346
347 if(uCount == 0) {
348 // Nothing to do for empty definite lenth arrays. They are just are
349 // effectively the same as an item that is not a map or array
350 goto Done;
351 // Empty indefinite length maps and arrays are handled elsewhere
352 }
353
354 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700355 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
356 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
357 uError = QCBOR_ERR_ARRAY_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700358 goto Done;
359 }
360
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700361 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700362 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700363 goto Done;
364 }
365
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700366 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700367 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
368 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700369
370 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700371
372Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700373 return uError;;
374}
375
376
377static inline void
378DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
379{
380 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
381}
382
383
384static inline void
385DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
386{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700387 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700388 pNesting->pCurrentBounded--;
389 if(DecodeNesting_IsCurrentBounded(pNesting)) {
390 break;
391 }
392 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700393}
394
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700395static inline void
396DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
397{
398 pNesting->pCurrent = pNesting->pCurrentBounded;
399}
400
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700401
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700402inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700403DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700404 uint32_t uEndOffset,
405 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700406{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700407 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700408
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700409 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700410 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700411 goto Done;
412 }
413
Laurence Lundblade02625d42020-06-25 14:41:41 -0700414 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700415 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
416 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700417
Laurence Lundblade02625d42020-06-25 14:41:41 -0700418 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700419 pNesting->pCurrentBounded = pNesting->pCurrent;
420
421Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700422 return uError;;
423}
424
Laurence Lundbladed0304932020-06-27 10:59:38 -0700425
426static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700427DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700428{
429 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700430}
431
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700432
Laurence Lundbladeee851742020-01-08 08:37:05 -0800433inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700434DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700435{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700436 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700437 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
438 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700439}
440
441
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700442inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700443DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700444{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700445 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700446 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700447 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700448}
449
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700450
Laurence Lundblade02625d42020-06-25 14:41:41 -0700451static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700452DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700453{
454 *pNesting = *pSave;
455}
456
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700457
Laurence Lundblade02625d42020-06-25 14:41:41 -0700458static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700459DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700460{
461 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
462}
463
464
Laurence Lundblade02625d42020-06-25 14:41:41 -0700465static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700466DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700467{
468 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
469}
470
471
Laurence Lundblade02625d42020-06-25 14:41:41 -0700472#include <stdio.h>
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700473
474const char *TypeStr(uint8_t type)
475{
476 switch(type) {
477 case QCBOR_TYPE_MAP: return " map";
478 case QCBOR_TYPE_ARRAY: return "array";
479 case QCBOR_TYPE_BYTE_STRING: return " bstr";
480 default: return " --- ";
481 }
482}
483
484static char buf[20]; // Not thread safe, but that is OK
485const char *CountString(uint16_t uCount, uint16_t uTotal)
486{
487 if(uTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
488 strcpy(buf, "indefinite");
489 } else {
490 sprintf(buf, "%d/%d", uCount, uTotal);
491 }
492 return buf;
493}
494
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700495
Laurence Lundblade02625d42020-06-25 14:41:41 -0700496void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700497{
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700498#if 0
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700499 printf("---%s--%d/%d--\narrow is current bounded level\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700500 szName,
501 (uint32_t)pBuf->cursor,
502 (uint32_t)pBuf->UB.len);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700503
504 printf("Level Type Count Offsets \n");
Laurence Lundblade02625d42020-06-25 14:41:41 -0700505 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700506 if(&(pNesting->pLevels[i]) > pNesting->pCurrent) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700507 break;
508 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700509
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700510 printf("%2s %2d %s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700511 pNesting->pCurrentBounded == &(pNesting->pLevels[i]) ? "->": " ",
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700512 i,
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700513 TypeStr(pNesting->pLevels[i].uLevelType));
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700514
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700515 if(pNesting->pLevels[i].uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700516 printf(" %5d %5d",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700517 pNesting->pLevels[i].u.bs.uEndOfBstr,
518 pNesting->pLevels[i].u.bs.uPreviousEndOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700519
520 } else {
521 printf("%10.10s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700522 CountString(pNesting->pLevels[i].u.ma.uCountCursor,
523 pNesting->pLevels[i].u.ma.uCountTotal));
524 if(pNesting->pLevels[i].u.ma.uStartOffset != UINT32_MAX) {
525 printf("Bounded start: %u",pNesting->pLevels[i].u.ma.uStartOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700526 }
527 }
528
529 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700530 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700531 printf("\n");
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700532#endif
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700533}
534
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700535
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700536
Laurence Lundbladeee851742020-01-08 08:37:05 -0800537/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800538 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
539
540 The following four functions are pretty wrappers for invocation of
541 the string allocator supplied by the caller.
542
Laurence Lundbladeee851742020-01-08 08:37:05 -0800543 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800544
Laurence Lundbladeee851742020-01-08 08:37:05 -0800545static inline void
546StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800547{
548 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
549}
550
Laurence Lundbladeee851742020-01-08 08:37:05 -0800551// StringAllocator_Reallocate called with pMem NULL is
552// equal to StringAllocator_Allocate()
553static inline UsefulBuf
554StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
555 void *pMem,
556 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800557{
558 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
559}
560
Laurence Lundbladeee851742020-01-08 08:37:05 -0800561static inline UsefulBuf
562StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800563{
564 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
565}
566
Laurence Lundbladeee851742020-01-08 08:37:05 -0800567static inline void
568StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800569{
570 if(pMe->pfAllocator) {
571 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
572 }
573}
574
575
576
Laurence Lundbladeee851742020-01-08 08:37:05 -0800577/*===========================================================================
578 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700579
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800580 See qcbor/qcbor_decode.h for definition of the object
581 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800582 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700583/*
584 Public function, see header file
585 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800586void QCBORDecode_Init(QCBORDecodeContext *me,
587 UsefulBufC EncodedCBOR,
588 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700589{
590 memset(me, 0, sizeof(QCBORDecodeContext));
591 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800592 // Don't bother with error check on decode mode. If a bad value is
593 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700594 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700595 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700596 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700597 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700598 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700599}
600
601
602/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700603 Public function, see header file
604 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800605void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
606 QCBORStringAllocate pfAllocateFunction,
607 void *pAllocateContext,
608 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700609{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800610 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
611 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
612 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700613}
614
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800615
616/*
617 Public function, see header file
618 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700619void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800620 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700621{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700622 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700623 (void)pMe;
624 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700625}
626
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700627
628/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800629 This decodes the fundamental part of a CBOR data item, the type and
630 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800631
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700632 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800633
Laurence Lundbladeee851742020-01-08 08:37:05 -0800634 This does the network->host byte order conversion. The conversion
635 here also results in the conversion for floats in addition to that
636 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800637
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700638 This returns:
639 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800640
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800641 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800642 tags and floats and length for strings and arrays
643
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800644 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800645 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800646
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800647 The int type is preferred to uint8_t for some variables as this
648 avoids integer promotions, can reduce code size and makes
649 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700650
651 @retval QCBOR_ERR_UNSUPPORTED
652
653 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700654 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800655inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
656 int *pnMajorType,
657 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800658 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700659{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700660 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800661
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700662 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800663 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800664
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700665 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800666 const int nTmpMajorType = nInitialByte >> 5;
667 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800668
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800669 // Where the number or argument accumulates
670 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800671
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800672 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700673 // Need to get 1,2,4 or 8 additional argument bytes. Map
674 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800675 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800676
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800677 // Loop getting all the bytes in the argument
678 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800679 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800680 // This shift and add gives the endian conversion
681 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
682 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800683 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800684 // The reserved and thus-far unused additional info values
685 nReturn = QCBOR_ERR_UNSUPPORTED;
686 goto Done;
687 } else {
688 // Less than 24, additional info is argument or 31, an indefinite length
689 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800690 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700691 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800692
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700693 if(UsefulInputBuf_GetError(pUInBuf)) {
694 nReturn = QCBOR_ERR_HIT_END;
695 goto Done;
696 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800697
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700698 // All successful if we got here.
699 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800700 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800701 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800702 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800703
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700704Done:
705 return nReturn;
706}
707
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800708
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700709/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800710 CBOR doesn't explicitly specify two's compliment for integers but all
711 CPUs use it these days and the test vectors in the RFC are so. All
712 integers in the CBOR structure are positive and the major type
713 indicates positive or negative. CBOR can express positive integers
714 up to 2^x - 1 where x is the number of bits and negative integers
715 down to 2^x. Note that negative numbers can be one more away from
716 zero than positive. Stdint, as far as I can tell, uses two's
717 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800718
Laurence Lundblade9b334962020-08-27 10:55:53 -0700719 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800720 used carefully here, and in particular why it isn't used in the interface.
721 Also see
722 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
723
724 Int is used for values that need less than 16-bits and would be subject
725 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700726
727 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700728 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800729inline static QCBORError
730DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700731{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700732 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800733
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700734 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
735 if (uNumber <= INT64_MAX) {
736 pDecodedItem->val.int64 = (int64_t)uNumber;
737 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800738
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700739 } else {
740 pDecodedItem->val.uint64 = uNumber;
741 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800742
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700743 }
744 } else {
745 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800746 // CBOR's representation of negative numbers lines up with the
747 // two-compliment representation. A negative integer has one
748 // more in range than a positive integer. INT64_MIN is
749 // equal to (-INT64_MAX) - 1.
750 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700751 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800752
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700753 } else {
754 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000755 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700756 nReturn = QCBOR_ERR_INT_OVERFLOW;
757 }
758 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800759
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700760 return nReturn;
761}
762
763// Make sure #define value line up as DecodeSimple counts on this.
764#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
765#error QCBOR_TYPE_FALSE macro value wrong
766#endif
767
768#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
769#error QCBOR_TYPE_TRUE macro value wrong
770#endif
771
772#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
773#error QCBOR_TYPE_NULL macro value wrong
774#endif
775
776#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
777#error QCBOR_TYPE_UNDEF macro value wrong
778#endif
779
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700780#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
781#error QCBOR_TYPE_BREAK macro value wrong
782#endif
783
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700784#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
785#error QCBOR_TYPE_DOUBLE macro value wrong
786#endif
787
788#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
789#error QCBOR_TYPE_FLOAT macro value wrong
790#endif
791
792/*
793 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700794
795 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
796
797 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700798 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800799inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800800DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700801{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700802 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800803
Laurence Lundbladeee851742020-01-08 08:37:05 -0800804 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800805 // above make sure uAdditionalInfo values line up with uDataType values.
806 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
807 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800808
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800809 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800810 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
811 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800812
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700813 case HALF_PREC_FLOAT:
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700814#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700815 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700816 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700817 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700818 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
819 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700820#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700821 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700822#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700823 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700824 case SINGLE_PREC_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700825 // Single precision is normally returned as a double
826 // since double is widely supported, there is no loss of
827 // precision, it makes it easy for the caller in
828 // most cases and it can be converted back to single
829 // with no loss of precision
830 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700831 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700832 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700833 {
834 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
835#ifndef QCBOR_DISABLE_FLOAT_HW_USE
836 // In the normal case, use HW to convert float to double.
837 pDecodedItem->val.dfnum = (double)f;
838 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700839#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700840 // Use of float HW is disabled, return as a float.
841 pDecodedItem->val.fnum = f;
842 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
843
844 // IEEE754_FloatToDouble() could be used here to return
845 // as a double, but it adds object code and most likely
846 // anyone disabling FLOAT HW use doesn't care about
847 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700848#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700849 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700850 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700851
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700852 case DOUBLE_PREC_FLOAT:
853 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700854 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700855 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800856
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700857 case CBOR_SIMPLEV_FALSE: // 20
858 case CBOR_SIMPLEV_TRUE: // 21
859 case CBOR_SIMPLEV_NULL: // 22
860 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700861 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700862 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800863
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700864 case CBOR_SIMPLEV_ONEBYTE: // 24
865 if(uNumber <= CBOR_SIMPLE_BREAK) {
866 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700867 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700868 goto Done;
869 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800870 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700871 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800872
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700873 default: // 0-19
874 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800875 /*
876 DecodeTypeAndNumber will make uNumber equal to
877 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
878 safe because the 2, 4 and 8 byte lengths of uNumber are in
879 the double/float cases above
880 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700881 pDecodedItem->val.uSimple = (uint8_t)uNumber;
882 break;
883 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800884
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700885Done:
886 return nReturn;
887}
888
889
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700890/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530891 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700892
893 @retval QCBOR_ERR_HIT_END
894
895 @retval QCBOR_ERR_STRING_ALLOCATE
896
897 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700898 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800899inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
900 int nMajorType,
901 uint64_t uStrLen,
902 UsefulInputBuf *pUInBuf,
903 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700904{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700905 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800906
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800907 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
908 // This check makes the casts to size_t below safe.
909
910 // 4 bytes less than the largest sizeof() so this can be tested by
911 // putting a SIZE_MAX length in the CBOR test input (no one will
912 // care the limit on strings is 4 bytes shorter).
913 if(uStrLen > SIZE_MAX-4) {
914 nReturn = QCBOR_ERR_STRING_TOO_LONG;
915 goto Done;
916 }
917
918 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530919 if(UsefulBuf_IsNULLC(Bytes)) {
920 // Failed to get the bytes for this string item
921 nReturn = QCBOR_ERR_HIT_END;
922 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700923 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530924
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800925 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530926 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800927 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530928 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700929 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530930 goto Done;
931 }
932 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800933 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530934 } else {
935 // Normal case with no string allocator
936 pDecodedItem->val.string = Bytes;
937 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800938 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800939 // Cast because ternary operator causes promotion to integer
940 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
941 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800942
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530943Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700944 return nReturn;
945}
946
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700947
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800948
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700949
950
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700951
952
Laurence Lundbladeee851742020-01-08 08:37:05 -0800953// Make sure the constants align as this is assumed by
954// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700955#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
956#error QCBOR_TYPE_ARRAY value not lined up with major type
957#endif
958#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
959#error QCBOR_TYPE_MAP value not lined up with major type
960#endif
961
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700962/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800963 This gets a single data item and decodes it including preceding
964 optional tagging. This does not deal with arrays and maps and nesting
965 except to decode the data item introducing them. Arrays and maps are
966 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800967
Laurence Lundbladeee851742020-01-08 08:37:05 -0800968 Errors detected here include: an array that is too long to decode,
969 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700970
971 @retval QCBOR_ERR_UNSUPPORTED
972
973 @retval QCBOR_ERR_HIT_END
974
975 @retval QCBOR_ERR_INT_OVERFLOW
976
977 @retval QCBOR_ERR_STRING_ALLOCATE
978
979 @retval QCBOR_ERR_STRING_TOO_LONG
980
981 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
982
983 @retval QCBOR_ERR_BAD_TYPE_7
984
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700985 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800986static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
987 QCBORItem *pDecodedItem,
988 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700989{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700990 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800991
Laurence Lundbladeee851742020-01-08 08:37:05 -0800992 /*
993 Get the major type and the number. Number could be length of more
994 bytes or the value depending on the major type nAdditionalInfo is
995 an encoding of the length of the uNumber and is needed to decode
996 floats and doubles
997 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800998 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700999 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001000 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001001
Laurence Lundblade4b09f632019-10-09 14:34:59 -07001002 memset(pDecodedItem, 0, sizeof(QCBORItem));
1003
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001004 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001005
Laurence Lundbladeee851742020-01-08 08:37:05 -08001006 // Error out here if we got into trouble on the type and number. The
1007 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001008 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001010 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001011
Laurence Lundbladeee851742020-01-08 08:37:05 -08001012 // At this point the major type and the value are valid. We've got
1013 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001014 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001015 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
1016 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001017 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001018 nReturn = QCBOR_ERR_BAD_INT;
1019 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001020 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001021 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001022 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001023
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001024 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
1025 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001026 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1027 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
1028 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
1029 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +05301030 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001031 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001032 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001033 }
1034 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001035
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001036 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
1037 case CBOR_MAJOR_TYPE_MAP: // Major type 5
1038 // Record the number of items in the array or map
1039 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
1040 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1041 goto Done;
1042 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001043 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001044 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001045 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001046 // type conversion OK because of check above
1047 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001048 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001049 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001050 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
1051 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001052 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001053
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001054 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001055 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001056 nReturn = QCBOR_ERR_BAD_INT;
1057 } else {
1058 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001059 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001060 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001061 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001062
Laurence Lundbladeee851742020-01-08 08:37:05 -08001063 case CBOR_MAJOR_TYPE_SIMPLE:
1064 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001065 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001066 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001067
Laurence Lundbladeee851742020-01-08 08:37:05 -08001068 default:
1069 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001070 nReturn = QCBOR_ERR_UNSUPPORTED;
1071 break;
1072 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001073
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001074Done:
1075 return nReturn;
1076}
1077
1078
1079
1080/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001081 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001082 individual chunk items together into one QCBORItem using the string
1083 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001084
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301085 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade9b334962020-08-27 10:55:53 -07001086
1087 @retval QCBOR_ERR_UNSUPPORTED
1088
1089 @retval QCBOR_ERR_HIT_END
1090
1091 @retval QCBOR_ERR_INT_OVERFLOW
1092
1093 @retval QCBOR_ERR_STRING_ALLOCATE
1094
1095 @retval QCBOR_ERR_STRING_TOO_LONG
1096
1097 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1098
1099 @retval QCBOR_ERR_BAD_TYPE_7
1100
1101 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1102
1103 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001104 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001105static inline QCBORError
1106GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001107{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001108 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001109
1110 // Get pointer to string allocator. First use is to pass it to
1111 // GetNext_Item() when option is set to allocate for *every* string.
1112 // Second use here is to allocate space to coallese indefinite
1113 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001114 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1115 &(me->StringAllocator) :
1116 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001117
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001118 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001119 nReturn = GetNext_Item(&(me->InBuf),
1120 pDecodedItem,
1121 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001122 if(nReturn) {
1123 goto Done;
1124 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001125
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001126 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301127 // code in this function from here down can be eliminated. Run tests, except
1128 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001129
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001130 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001131 const uint8_t uStringType = pDecodedItem->uDataType;
1132 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001133 goto Done; // no need to do any work here on non-string types
1134 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001135
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001136 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301137 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001138 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001139 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001140
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301141 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001142 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001143 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1144 goto Done;
1145 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001146
Laurence Lundblade4b270642020-08-14 12:53:07 -07001147 // Loop getting chunks of the indefinite length string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001148 UsefulBufC FullString = NULLUsefulBufC;
1149
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001150 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001151 // Get item for next chunk
1152 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001153 // NULL string allocator passed here. Do not need to allocate
1154 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001155 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001156 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001157 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001158 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001159
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301160 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001161 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001162 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001163 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301164 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001165 break;
1166 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001167
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001168 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301169 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001170 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001171 if(StringChunkItem.uDataType != uStringType ||
1172 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001173 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001174 break;
1175 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001176
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301177 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001178 // The first time throurgh FullString.ptr is NULL and this is
1179 // equivalent to StringAllocator_Allocate()
1180 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1181 UNCONST_POINTER(FullString.ptr),
1182 FullString.len + StringChunkItem.val.string.len);
1183
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001184 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301185 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001186 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001187 break;
1188 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001189
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001190 // Copy new string chunk at the end of string so far.
1191 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001192 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001193
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001194 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1195 // Getting the item failed, clean up the allocated memory
1196 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001197 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001198
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001199Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001200 return nReturn;
1201}
1202
Laurence Lundblade9b334962020-08-27 10:55:53 -07001203static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001204 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001205 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001206 } else if(uTagVal == CBOR_TAG_INVALID16) {
1207 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001208 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001209 const int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001210 return me->auMappedTags[x];
1211 }
1212}
1213
Laurence Lundblade9b334962020-08-27 10:55:53 -07001214
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001215/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001216 Gets all optional tag data items preceding a data item that is not an
1217 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001218
1219 @retval QCBOR_ERR_UNSUPPORTED
1220
1221 @retval QCBOR_ERR_HIT_END
1222
1223 @retval QCBOR_ERR_INT_OVERFLOW
1224
1225 @retval QCBOR_ERR_STRING_ALLOCATE
1226
1227 @retval QCBOR_ERR_STRING_TOO_LONG
1228
1229 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1230
1231 @retval QCBOR_ERR_BAD_TYPE_7
1232
1233 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1234
1235 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1236
1237 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001238 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001239static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001240GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001241{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001242 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1243 CBOR_TAG_INVALID16,
1244 CBOR_TAG_INVALID16,
1245 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001246
Laurence Lundblade9b334962020-08-27 10:55:53 -07001247 QCBORError uReturn = QCBOR_SUCCESS;
1248
Laurence Lundblade59289e52019-12-30 13:44:37 -08001249 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001250 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001251 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1252 if(uErr != QCBOR_SUCCESS) {
1253 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001254 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001255 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001256
Laurence Lundblade9b334962020-08-27 10:55:53 -07001257 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001258 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001259 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001260 break;
1261 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001262
Laurence Lundblade9b334962020-08-27 10:55:53 -07001263 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1264 // No room in the tag list
1265 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1266 // Continue on to get all tags on this item even though
1267 // it is erroring out in the end. This is a resource limit
1268 // error, not an problem with being well-formed CBOR.
1269 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001270 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001271 // Slide tags over one in the array to make room at index 0
1272 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1273 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001274 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001275
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001276 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001277 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001278 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001279 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001280 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001281 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001282 break;
1283 }
1284 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1285 break;
1286 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001287 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001288 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1289 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001290 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1291 // Continue on to get all tags on this item even though
1292 // it is erroring out in the end. This is a resource limit
1293 // error, not an problem with being well-formed CBOR.
1294 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001295 }
1296
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001297 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001298 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001299 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001300
1301 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001302 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001303 }
1304 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001305
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001306Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001307 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001308}
1309
1310
1311/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001312 This layer takes care of map entries. It combines the label and data
1313 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001314
1315 @retval QCBOR_ERR_UNSUPPORTED
1316
1317 @retval QCBOR_ERR_HIT_END
1318
1319 @retval QCBOR_ERR_INT_OVERFLOW
1320
1321 @retval QCBOR_ERR_STRING_ALLOCATE
1322
1323 @retval QCBOR_ERR_STRING_TOO_LONG
1324
1325 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1326
1327 @retval QCBOR_ERR_BAD_TYPE_7
1328
1329 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1330
1331 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1332
1333 @retval QCBOR_ERR_TOO_MANY_TAGS
1334
1335 @retval QCBOR_ERR_MAP_LABEL_TYPE
1336
1337 @retval QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001338 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001339static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001340GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001341{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001342 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001343 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001344 if(nReturn)
1345 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001346
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001347 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001348 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001349 goto Done;
1350 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001351
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001352 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1353 // In a map and caller wants maps decoded, not treated as arrays
1354
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001355 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001356 // If in a map and the right decoding mode, get the label
1357
Laurence Lundbladeee851742020-01-08 08:37:05 -08001358 // Save label in pDecodedItem and get the next which will
1359 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001360 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001361 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001362 if(nReturn)
1363 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001364
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301365 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001366
1367 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1368 // strings are always good labels
1369 pDecodedItem->label.string = LabelItem.val.string;
1370 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1371 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001372 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001373 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1374 goto Done;
1375 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1376 pDecodedItem->label.int64 = LabelItem.val.int64;
1377 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1378 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1379 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1380 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1381 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1382 pDecodedItem->label.string = LabelItem.val.string;
1383 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1384 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1385 } else {
1386 // label is not an int or a string. It is an arrray
1387 // or a float or such and this implementation doesn't handle that.
1388 // Also, tags on labels are ignored.
1389 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1390 goto Done;
1391 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001392 }
1393 } else {
1394 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001395 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1396 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1397 goto Done;
1398 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001399 // Decoding a map as an array
1400 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001401 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1402 // Cast is needed because of integer promotion
1403 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001404 }
1405 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001406
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001407Done:
1408 return nReturn;
1409}
1410
1411
Laurence Lundblade02625d42020-06-25 14:41:41 -07001412/*
1413 See if next item is a CBOR break. If it is, it is consumed,
1414 if not it is not consumed.
1415*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001416static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001417NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1418{
1419 *pbNextIsBreak = false;
1420 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001421 QCBORItem Peek;
1422 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1423 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1424 if(uReturn != QCBOR_SUCCESS) {
1425 return uReturn;
1426 }
1427 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001428 // It is not a break, rewind so it can be processed normally.
1429 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001430 } else {
1431 *pbNextIsBreak = true;
1432 }
1433 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001434
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001435 return QCBOR_SUCCESS;
1436}
1437
1438
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001439/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001440 An item was just consumed, now figure out if it was the
1441 end of an array or map that can be closed out. That
1442 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001443*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001444static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001445{
1446 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001447
Laurence Lundblade642282a2020-06-23 12:00:33 -07001448 /* This loops ascending nesting levels as long as there is ascending to do */
1449 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1450
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001451 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001452 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001453 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1454 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001455 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001456 break;
1457 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001458 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001459
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001460 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001461 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001462 bool bIsBreak = false;
1463 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1464 if(uReturn != QCBOR_SUCCESS) {
1465 goto Done;
1466 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001467
1468 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001469 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001470 break;
1471 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001472
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001473 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001474 /*
1475 Break occurred inside a bstr-wrapped CBOR or
1476 in the top level sequence. This is always an
1477 error because neither are an indefinte length
1478 map/array.
1479 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001480 uReturn = QCBOR_ERR_BAD_BREAK;
1481 goto Done;
1482 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001483
Laurence Lundblade02625d42020-06-25 14:41:41 -07001484 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001485 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001486
Laurence Lundblade02625d42020-06-25 14:41:41 -07001487 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001488
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001489 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001490 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001491 /* 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 -07001492 if(bMarkEnd) {
1493 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001494 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001495
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001496 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001497 break;
1498 }
1499
1500 /* Finally, actually ascend one level. */
1501 DecodeNesting_Ascend(&(pMe->nesting));
1502 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001503
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001504 uReturn = QCBOR_SUCCESS;
1505
1506Done:
1507 return uReturn;
1508}
1509
1510
1511/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001512 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001513 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1514 indefinte length maps and arrays by looking at the item count or
1515 finding CBOR breaks. It detects the ends of the top-level sequence
1516 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001517
1518 @retval QCBOR_ERR_UNSUPPORTED X
1519
1520 @retval QCBOR_ERR_HIT_END
1521
1522 @retval QCBOR_ERR_INT_OVERFLOW X
1523
1524 @retval QCBOR_ERR_STRING_ALLOCATE
1525
1526 @retval QCBOR_ERR_STRING_TOO_LONG
1527
1528 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1529
1530 @retval QCBOR_ERR_BAD_TYPE_7 X
1531
1532 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1533
1534 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1535
1536 @retval QCBOR_ERR_TOO_MANY_TAGS
1537
1538 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1539
1540 @retval QCBOR_ERR_ARRAY_TOO_LONG
1541
1542 @retval QCBOR_ERR_NO_MORE_ITEMS
1543
1544 @retval QCBOR_ERR_BAD_BREAK
1545
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001546 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001547static QCBORError
1548QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001549{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001550 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001551 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001552
Laurence Lundblade642282a2020-06-23 12:00:33 -07001553 /*
1554 If out of bytes to consume, it is either the end of the top-level
1555 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001556
Laurence Lundblade642282a2020-06-23 12:00:33 -07001557 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1558 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1559 CBOR is exited, the length is set back to the top-level's length
1560 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001561 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001562 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001563 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001564 goto Done;
1565 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001566
Laurence Lundblade642282a2020-06-23 12:00:33 -07001567 /*
1568 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001569 array. The check for the end of an indefinite length array is
1570 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001571 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001572 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001573 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001574 goto Done;
1575 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001576
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001577 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001578 uReturn = GetNext_MapEntry(me, pDecodedItem);
1579 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001580 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001581 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301582
Laurence Lundblade642282a2020-06-23 12:00:33 -07001583 /*
1584 Breaks ending arrays/maps are always processed at the end of this
1585 function. They should never show up here.
1586 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301587 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001588 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301589 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301590 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001591
Laurence Lundblade642282a2020-06-23 12:00:33 -07001592 /*
1593 Record the nesting level for this data item before processing any
1594 of decrementing and descending.
1595 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001596 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001597
Laurence Lundblade642282a2020-06-23 12:00:33 -07001598
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001599 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001600 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001601 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001602 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001603
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001604 Empty indefinite length maps and arrays are descended into, but then ascended out
Laurence Lundblade02625d42020-06-25 14:41:41 -07001605 of in the next chunk of code.
1606
1607 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001608 encloses them so a decrement needs to be done for them too, but
1609 that is done only when all the items in them have been
1610 processed, not when they are opened with the exception of an
1611 empty map or array.
1612 */
1613 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1614 pDecodedItem->uDataType,
1615 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001616 if(uReturn != QCBOR_SUCCESS) {
1617 goto Done;
1618 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001619 }
1620
Laurence Lundblade02625d42020-06-25 14:41:41 -07001621 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1622 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1623 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001624 /*
1625 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001626 - A non-aggregate like an integer or string
1627 - An empty definite length map or array
1628 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001629
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001630 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001631 definite length map/array and break detection for an indefinite
1632 length map/array. If the end of the map/array was reached, then
1633 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001634 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001635 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001636 if(uReturn) {
1637 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001638 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301639 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001640
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001641 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001642 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001643 Tell the caller what level is next. This tells them what
1644 maps/arrays were closed out and makes it possible for them to
1645 reconstruct the tree with just the information returned in
1646 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001647 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001648 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001649 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001650 pDecodedItem->uNextNestLevel = 0;
1651 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001652 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001653 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001654
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001655Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001656 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001657 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001658 memset(pDecodedItem, 0, sizeof(QCBORItem));
1659 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001660 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001661}
1662
Laurence Lundblade9b334962020-08-27 10:55:53 -07001663static void ShiftTags(QCBORItem *pDecodedItem)
1664{
1665 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1666 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1667 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1668 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1669}
1670
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001671
Laurence Lundblade59289e52019-12-30 13:44:37 -08001672/*
1673 Mostly just assign the right data type for the date string.
1674 */
1675inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1676{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001677 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1678 return QCBOR_ERR_BAD_OPT_TAG;
1679 }
1680
1681 const UsefulBufC Temp = pDecodedItem->val.string;
1682 pDecodedItem->val.dateString = Temp;
1683 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001684 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001685 return QCBOR_SUCCESS;
1686}
1687
1688
Laurence Lundblade9b334962020-08-27 10:55:53 -07001689
Laurence Lundblade59289e52019-12-30 13:44:37 -08001690/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001691 The epoch formatted date. Turns lots of different forms of encoding
1692 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001693 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001694static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001695{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001696 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001697
1698 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1699
1700 switch (pDecodedItem->uDataType) {
1701
1702 case QCBOR_TYPE_INT64:
1703 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1704 break;
1705
1706 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001707 // This only happens for CBOR type 0 > INT64_MAX so it is
1708 // always an overflow.
1709 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1710 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001711 break;
1712
1713 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001714 case QCBOR_TYPE_FLOAT:
1715#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001716 {
1717 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001718 // conversion to an int64_t to be able to detect doubles that
1719 // are too large to fit into an int64_t. A double has 52
1720 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1721 // to a double actually causes a round up which is bad and
1722 // wrong for the comparison because it will allow conversion
1723 // of doubles that can't fit into a uint64_t. To remedy this
1724 // INT64_MAX - 0x7ff is used as the cutoff point because if
1725 // that value rounds up in conversion to double it will still
1726 // be less than INT64_MAX. 0x7ff is picked because it has 11
1727 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001728 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001729 // INT64_MAX seconds is on the order of 10 billion years, and
1730 // the earth is less than 5 billion years old, so for most
1731 // uses this conversion error won't occur even though doubles
1732 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001733 //
1734 // Without the 0x7ff there is a ~30 minute range of time
1735 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001736 // where this code would go wrong. Some compilers
1737 // will generate warnings or errors without the 0x7ff
1738 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001739 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1740 pDecodedItem->val.dfnum :
1741 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001742 if(isnan(d) ||
1743 d > (double)(INT64_MAX - 0x7ff) ||
1744 d < (double)(INT64_MIN + 0x7ff)) {
1745 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001746 goto Done;
1747 }
1748 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001749 pDecodedItem->val.epochDate.fSecondsFraction =
1750 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001751 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001752#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001753
Laurence Lundbladec7114722020-08-13 05:11:40 -07001754 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001755 goto Done;
1756
Laurence Lundblade9682a532020-06-06 18:33:04 -07001757#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001758 break;
1759
1760 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001761 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001762 goto Done;
1763 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001764
Laurence Lundblade59289e52019-12-30 13:44:37 -08001765 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1766
1767Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001768 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001769}
1770
1771
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001772/*
1773 Mostly just assign the right data type for the bignum.
1774 */
1775inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1776{
1777 // Stack Use: UsefulBuf 1 -- 16
1778 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1779 return QCBOR_ERR_BAD_OPT_TAG;
1780 }
1781 const UsefulBufC Temp = pDecodedItem->val.string;
1782 pDecodedItem->val.bigNum = Temp;
1783 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1784 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1785 : QCBOR_TYPE_NEGBIGNUM);
1786 return QCBOR_SUCCESS;
1787}
1788
1789
Laurence Lundblade59289e52019-12-30 13:44:37 -08001790#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1791/*
1792 Decode decimal fractions and big floats.
1793
1794 When called pDecodedItem must be the array that is tagged as a big
1795 float or decimal fraction, the array that has the two members, the
1796 exponent and mantissa.
1797
1798 This will fetch and decode the exponent and mantissa and put the
1799 result back into pDecodedItem.
1800 */
1801inline static QCBORError
1802QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1803{
1804 QCBORError nReturn;
1805
1806 // --- Make sure it is an array; track nesting level of members ---
1807 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1808 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1809 goto Done;
1810 }
1811
1812 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001813 // definite length arrays, but not for indefnite. Instead remember
1814 // the nesting level the two integers must be at, which is one
1815 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001816 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1817
1818 // --- Is it a decimal fraction or a bigfloat? ---
1819 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1820 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1821
1822 // --- Get the exponent ---
1823 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001824 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001825 if(nReturn != QCBOR_SUCCESS) {
1826 goto Done;
1827 }
1828 if(exponentItem.uNestingLevel != nNestLevel) {
1829 // Array is empty or a map/array encountered when expecting an int
1830 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1831 goto Done;
1832 }
1833 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1834 // Data arriving as an unsigned int < INT64_MAX has been converted
1835 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1836 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1837 // will be too large for this to handle and thus an error that will
1838 // get handled in the next else.
1839 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1840 } else {
1841 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1842 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1843 goto Done;
1844 }
1845
1846 // --- Get the mantissa ---
1847 QCBORItem mantissaItem;
1848 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1849 if(nReturn != QCBOR_SUCCESS) {
1850 goto Done;
1851 }
1852 if(mantissaItem.uNestingLevel != nNestLevel) {
1853 // Mantissa missing or map/array encountered when expecting number
1854 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1855 goto Done;
1856 }
1857 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1858 // Data arriving as an unsigned int < INT64_MAX has been converted
1859 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1860 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1861 // will be too large for this to handle and thus an error that
1862 // will get handled in an else below.
1863 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1864 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1865 // Got a good big num mantissa
1866 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1867 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001868 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1869 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1870 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001871 } else {
1872 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1873 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1874 goto Done;
1875 }
1876
1877 // --- Check that array only has the two numbers ---
1878 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001879 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001880 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1881 goto Done;
1882 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001883 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001884
1885Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001886 return nReturn;
1887}
1888#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1889
1890
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001891inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1892{
1893 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1894 return QCBOR_ERR_BAD_OPT_TAG;
1895 }
1896 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1897 return QCBOR_SUCCESS;
1898}
1899
1900
1901inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1902{
1903 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1904 return QCBOR_ERR_BAD_OPT_TAG;
1905 }
1906 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001907
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001908 return QCBOR_SUCCESS;
1909}
1910
1911
1912inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1913{
1914 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1915 return QCBOR_ERR_BAD_OPT_TAG;
1916 }
1917 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001918
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001919 return QCBOR_SUCCESS;
1920}
1921
1922
1923inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1924{
1925 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1926 return QCBOR_ERR_BAD_OPT_TAG;
1927 }
1928 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001929
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001930 return QCBOR_SUCCESS;
1931}
1932
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001933
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001934inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1935{
1936 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1937 return QCBOR_ERR_BAD_OPT_TAG;
1938 }
1939 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001940
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001941 return QCBOR_SUCCESS;
1942}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001943
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001944
1945inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1946{
1947 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1948 return QCBOR_ERR_BAD_OPT_TAG;
1949 }
1950 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001951
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001952 return QCBOR_SUCCESS;
1953}
1954
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001955
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001956inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1957{
1958 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1959 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001960 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001961 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1962 } else {
1963 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001964
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001965 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001966
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001967 return QCBOR_SUCCESS;
1968}
1969
1970
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001971inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1972{
1973 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1974 return QCBOR_ERR_BAD_OPT_TAG;
1975 }
1976 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001977
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001978 return QCBOR_SUCCESS;
1979}
1980
1981
Laurence Lundblade59289e52019-12-30 13:44:37 -08001982/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001983 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001984 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001985QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001986QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001987{
1988 QCBORError nReturn;
1989
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001990 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001991 if(nReturn != QCBOR_SUCCESS) {
1992 goto Done;
1993 }
1994
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001995 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001996 switch(pDecodedItem->uTags[i]) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001997
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001998 // Many of the functions here only just map a CBOR tag to
1999 // a QCBOR_TYPE for a string and could probably be
2000 // implemented with less object code. This implementation
2001 // of string types takes about 120 bytes of object code
2002 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002003 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002004 nReturn = DecodeDateString(pDecodedItem);
2005 break;
2006
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002007 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002008 nReturn = DecodeDateEpoch(pDecodedItem);
2009 break;
2010
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002011 case CBOR_TAG_POS_BIGNUM:
2012 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002013 nReturn = DecodeBigNum(pDecodedItem);
2014 break;
2015
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002016 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2017 case CBOR_TAG_DECIMAL_FRACTION:
2018 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002019 // For aggregate tagged types, what goes into pTags is only collected
2020 // from the surrounding data item, not the contents, so pTags is not
2021 // passed on here.
2022
2023 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
2024 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002025 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002026
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002027 case CBOR_TAG_CBOR:
2028 nReturn = DecodeWrappedCBOR(pDecodedItem);
2029 break;
2030
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002031 case CBOR_TAG_CBOR_SEQUENCE:
2032 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
2033 break;
2034
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002035 case CBOR_TAG_URI:
2036 nReturn = DecodeURI(pDecodedItem);
2037 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002038
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002039 case CBOR_TAG_B64URL:
2040 nReturn = DecodeB64URL(pDecodedItem);
2041 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002042
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002043 case CBOR_TAG_B64:
2044 nReturn = DecodeB64(pDecodedItem);
2045 break;
2046
2047 case CBOR_TAG_MIME:
2048 case CBOR_TAG_BINARY_MIME:
2049 nReturn = DecodeMIME(pDecodedItem);
2050 break;
2051
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002052 case CBOR_TAG_REGEX:
2053 nReturn = DecodeRegex(pDecodedItem);
2054 break;
2055
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002056 case CBOR_TAG_BIN_UUID:
2057 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002058 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002059
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002060 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002061 // The end of the tag list or no tags
2062 // Successful exit from the loop.
2063 goto Done;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002064
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002065 default:
2066 // A tag that is not understood
2067 // A successful exit from the loop
2068 goto Done;
2069
2070 }
2071 if(nReturn != QCBOR_SUCCESS) {
2072 goto Done;
2073 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002074 // A tag was successfully processed, shift it
2075 // out of the list of tags returned.
2076 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002077 }
2078
2079Done:
2080 if(nReturn != QCBOR_SUCCESS) {
2081 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2082 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2083 }
2084 return nReturn;
2085}
2086
2087
2088/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002089 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002090 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002091void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2092{
2093 if(pMe->uLastError != QCBOR_SUCCESS) {
2094 return;
2095 }
2096
2097 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2098}
2099
2100
2101/*
2102 Public function, see header qcbor/qcbor_decode.h file
2103 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002104QCBORError
2105QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2106 QCBORItem *pDecodedItem,
2107 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002108{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002109 QCBORError nReturn;
2110
2111 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2112 if(nReturn != QCBOR_SUCCESS) {
2113 return nReturn;
2114 }
2115
2116 if(pTags != NULL) {
2117 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002118 // Reverse the order because pTags is reverse of
2119 // QCBORItem.uTags.
2120 for(int i = QCBOR_MAX_TAGS_PER_ITEM-1; i >=0 ; i--) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002121 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002122 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002123 }
2124 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2125 return QCBOR_ERR_TOO_MANY_TAGS;
2126 }
2127 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
2128 pTags->uNumUsed++;
2129 }
2130 }
2131
2132 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002133}
2134
2135
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002136/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302137 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302138 next one down. If a layer has no work to do for a particular item
2139 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002140
Laurence Lundblade59289e52019-12-30 13:44:37 -08002141 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2142 tagged data items, turning them into the local C representation.
2143 For the most simple it is just associating a QCBOR_TYPE with the data. For
2144 the complex ones that an aggregate of data items, there is some further
2145 decoding and a little bit of recursion.
2146
2147 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302148 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302149 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002150 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002151
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302152 - GetNext_MapEntry -- This handles the combining of two
2153 items, the label and the data, that make up a map entry.
2154 It only does work on maps. It combines the label and data
2155 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002156
Laurence Lundblade59289e52019-12-30 13:44:37 -08002157 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2158 tags into bit flags associated with the data item. No actual decoding
2159 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002160
Laurence Lundblade59289e52019-12-30 13:44:37 -08002161 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302162 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302163 string allocater to create contiguous space for the item. It
2164 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002165
Laurence Lundblade59289e52019-12-30 13:44:37 -08002166 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2167 atomic data item has a "major type", an integer "argument" and optionally
2168 some content. For text and byte strings, the content is the bytes
2169 that make up the string. These are the smallest data items that are
2170 considered to be well-formed. The content may also be other data items in
2171 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002172
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002173 Roughly this takes 300 bytes of stack for vars. Need to
2174 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002175
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302176 */
2177
2178
2179/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002180 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002181 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002182bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002183 const QCBORItem *pItem,
2184 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002185{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002186 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002187 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002188 break;
2189 }
2190 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002191 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002192 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002193 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002194
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002195 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002196}
2197
2198
2199/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002200 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002201 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002202QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002203{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002204 QCBORError uReturn = me->uLastError;
2205
2206 if(uReturn != QCBOR_SUCCESS) {
2207 goto Done;
2208 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002209
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002210 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002211 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002212 uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002213 goto Done;
2214 }
2215
2216 // Error out if not all the bytes are consumed
2217 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002218 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002219 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002220
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002221Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302222 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002223 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002224 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002225
Laurence Lundblade085d7952020-07-24 10:26:30 -07002226 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002227}
2228
2229
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002230/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002231 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002232*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002233// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002234uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2235 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002236 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002237{
Laurence Lundblade9b334962020-08-27 10:55:53 -07002238 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2239 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002240 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002241 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002242 }
2243}
2244
Laurence Lundblade9b334962020-08-27 10:55:53 -07002245/*
2246 Public function, see header qcbor/qcbor_decode.h file
2247*/
2248uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2249 uint32_t uIndex)
2250{
2251 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2252 return CBOR_TAG_INVALID64;
2253 } else {
2254 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2255 }
2256}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002257
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002258/*
2259
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002260Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002261
Laurence Lundbladeee851742020-01-08 08:37:05 -08002262 - Hit end of input before it was expected while decoding type and
2263 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002264
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002265 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002266
Laurence Lundbladeee851742020-01-08 08:37:05 -08002267 - Hit end of input while decoding a text or byte string
2268 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002269
Laurence Lundbladeee851742020-01-08 08:37:05 -08002270 - Encountered conflicting tags -- e.g., an item is tagged both a date
2271 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002272
Laurence Lundbladeee851742020-01-08 08:37:05 -08002273 - Encontered an array or mapp that has too many items
2274 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002275
Laurence Lundbladeee851742020-01-08 08:37:05 -08002276 - Encountered array/map nesting that is too deep
2277 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002278
Laurence Lundbladeee851742020-01-08 08:37:05 -08002279 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2280 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002281
Laurence Lundbladeee851742020-01-08 08:37:05 -08002282 - The type of a map label is not a string or int
2283 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002284
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002285 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002286
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002287 */
2288
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002289
2290
Laurence Lundbladef6531662018-12-04 10:42:22 +09002291
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002292/* ===========================================================================
2293 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002294
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002295 This implements a simple sting allocator for indefinite length
2296 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2297 implements the function type QCBORStringAllocate and allows easy
2298 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002299
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002300 This particular allocator is built-in for convenience. The caller
2301 can implement their own. All of this following code will get
2302 dead-stripped if QCBORDecode_SetMemPool() is not called.
2303
2304 This is a very primitive memory allocator. It does not track
2305 individual allocations, only a high-water mark. A free or
2306 reallocation must be of the last chunk allocated.
2307
2308 The size of the pool and offset to free memory are packed into the
2309 first 8 bytes of the memory pool so we don't have to keep them in
2310 the decode context. Since the address of the pool may not be
2311 aligned, they have to be packed and unpacked as if they were
2312 serialized data of the wire or such.
2313
2314 The sizes packed in are uint32_t to be the same on all CPU types
2315 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002316 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002317
2318
Laurence Lundbladeee851742020-01-08 08:37:05 -08002319static inline int
2320MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002321{
2322 // Use of UsefulInputBuf is overkill, but it is convenient.
2323 UsefulInputBuf UIB;
2324
Laurence Lundbladeee851742020-01-08 08:37:05 -08002325 // Just assume the size here. It was checked during SetUp so
2326 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002327 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2328 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2329 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2330 return UsefulInputBuf_GetError(&UIB);
2331}
2332
2333
Laurence Lundbladeee851742020-01-08 08:37:05 -08002334static inline int
2335MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002336{
2337 // Use of UsefulOutBuf is overkill, but convenient. The
2338 // length check performed here is useful.
2339 UsefulOutBuf UOB;
2340
2341 UsefulOutBuf_Init(&UOB, Pool);
2342 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2343 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2344 return UsefulOutBuf_GetError(&UOB);
2345}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002346
2347
2348/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002349 Internal function for an allocation, reallocation free and destuct.
2350
2351 Having only one function rather than one each per mode saves space in
2352 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002353
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002354 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2355 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002356static UsefulBuf
2357MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002358{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002359 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002360
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002361 uint32_t uPoolSize;
2362 uint32_t uFreeOffset;
2363
2364 if(uNewSize > UINT32_MAX) {
2365 // This allocator is only good up to 4GB. This check should
2366 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2367 goto Done;
2368 }
2369 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2370
2371 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2372 goto Done;
2373 }
2374
2375 if(uNewSize) {
2376 if(pMem) {
2377 // REALLOCATION MODE
2378 // Calculate pointer to the end of the memory pool. It is
2379 // assumed that pPool + uPoolSize won't wrap around by
2380 // assuming the caller won't pass a pool buffer in that is
2381 // not in legitimate memory space.
2382 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2383
2384 // Check that the pointer for reallocation is in the range of the
2385 // pool. This also makes sure that pointer math further down
2386 // doesn't wrap under or over.
2387 if(pMem >= pPool && pMem < pPoolEnd) {
2388 // Offset to start of chunk for reallocation. This won't
2389 // wrap under because of check that pMem >= pPool. Cast
2390 // is safe because the pool is always less than UINT32_MAX
2391 // because of check in QCBORDecode_SetMemPool().
2392 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2393
2394 // Check to see if the allocation will fit. uPoolSize -
2395 // uMemOffset will not wrap under because of check that
2396 // pMem is in the range of the uPoolSize by check above.
2397 if(uNewSize <= uPoolSize - uMemOffset) {
2398 ReturnValue.ptr = pMem;
2399 ReturnValue.len = uNewSize;
2400
2401 // Addition won't wrap around over because uNewSize was
2402 // checked to be sure it is less than the pool size.
2403 uFreeOffset = uMemOffset + uNewSize32;
2404 }
2405 }
2406 } else {
2407 // ALLOCATION MODE
2408 // uPoolSize - uFreeOffset will not underflow because this
2409 // pool implementation makes sure uFreeOffset is always
2410 // smaller than uPoolSize through this check here and
2411 // reallocation case.
2412 if(uNewSize <= uPoolSize - uFreeOffset) {
2413 ReturnValue.len = uNewSize;
2414 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002415 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002416 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002417 }
2418 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002419 if(pMem) {
2420 // FREE MODE
2421 // Cast is safe because of limit on pool size in
2422 // QCBORDecode_SetMemPool()
2423 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2424 } else {
2425 // DESTRUCT MODE
2426 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002427 }
2428 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002429
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002430 UsefulBuf Pool = {pPool, uPoolSize};
2431 MemPool_Pack(Pool, uFreeOffset);
2432
2433Done:
2434 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002435}
2436
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002437
Laurence Lundbladef6531662018-12-04 10:42:22 +09002438/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002439 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002440 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002441QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2442 UsefulBuf Pool,
2443 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002444{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002445 // The pool size and free mem offset are packed into the beginning
2446 // of the pool memory. This compile time check make sure the
2447 // constant in the header is correct. This check should optimize
2448 // down to nothing.
2449 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002450 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002451 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002452
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002453 // The pool size and free offset packed in to the beginning of pool
2454 // memory are only 32-bits. This check will optimize out on 32-bit
2455 // machines.
2456 if(Pool.len > UINT32_MAX) {
2457 return QCBOR_ERR_BUFFER_TOO_LARGE;
2458 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002459
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002460 // This checks that the pool buffer given is big enough.
2461 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2462 return QCBOR_ERR_BUFFER_TOO_SMALL;
2463 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002464
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002465 pMe->StringAllocator.pfAllocator = MemPool_Function;
2466 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2467 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002468
Laurence Lundblade30816f22018-11-10 13:40:22 +07002469 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002470}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002471
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002472
2473
Laurence Lundblade9b334962020-08-27 10:55:53 -07002474static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2475{
2476 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2477}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002478
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002479
2480/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002481 Consume an entire map or array (and do next to
2482 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002483 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002484static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002485ConsumeItem(QCBORDecodeContext *pMe,
2486 const QCBORItem *pItemToConsume,
2487 uint_fast8_t *puNextNestLevel)
2488{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002489 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002490 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002491
Laurence Lundblade02625d42020-06-25 14:41:41 -07002492 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002493
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002494 // If it is a map or array, this will tell if it is empty.
2495 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2496
2497 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2498 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002499
Laurence Lundblade1341c592020-04-11 14:19:05 -07002500 /* This works for definite and indefinite length
2501 * maps and arrays by using the nesting level
2502 */
2503 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002504 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade4b270642020-08-14 12:53:07 -07002505 if( QCBORDecode_IsNotWellFormed(uReturn)) {
2506 // TODO: also resource limit errors
Laurence Lundblade1341c592020-04-11 14:19:05 -07002507 goto Done;
2508 }
2509 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002510
Laurence Lundblade1341c592020-04-11 14:19:05 -07002511 if(puNextNestLevel != NULL) {
2512 *puNextNestLevel = Item.uNextNestLevel;
2513 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002514 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002515
Laurence Lundblade1341c592020-04-11 14:19:05 -07002516 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002517 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002518 if(puNextNestLevel != NULL) {
2519 /* Just pass the nesting level through */
2520 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2521 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002522 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002523 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002524
2525Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002526 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002527}
2528
2529
Laurence Lundblade1341c592020-04-11 14:19:05 -07002530/* Return true if the labels in Item1 and Item2 are the same.
2531 Works only for integer and string labels. Returns false
2532 for any other type. */
2533static inline bool
2534MatchLabel(QCBORItem Item1, QCBORItem Item2)
2535{
2536 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2537 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2538 return true;
2539 }
2540 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002541 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002542 return true;
2543 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002544 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002545 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2546 return true;
2547 }
2548 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2549 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2550 return true;
2551 }
2552 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002553
Laurence Lundblade1341c592020-04-11 14:19:05 -07002554 /* Other label types are never matched */
2555 return false;
2556}
2557
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002558
2559/*
2560 Returns true if Item1 and Item2 are the same type
2561 or if either are of QCBOR_TYPE_ANY.
2562 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002563static inline bool
2564MatchType(QCBORItem Item1, QCBORItem Item2)
2565{
2566 if(Item1.uDataType == Item2.uDataType) {
2567 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002568 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002569 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002570 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002571 return true;
2572 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002573 return false;
2574}
2575
2576
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002577/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002578 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002579
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002580 @param[in] pMe The decode context to search.
2581 @param[in,out] pItemArray The items to search for and the items found.
2582 @param[out] puOffset Byte offset of last item matched.
2583 @param[in] pCBContext Context for the not-found item call back.
2584 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002585
2586 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2587
Laurence Lundblade9b334962020-08-27 10:55:53 -07002588 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label) were found
2589 for one of the labels being search for. This duplicate detection is only performed for items in pItemArray,
2590 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002591
2592 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2593
2594 @retval Also errors returned by QCBORDecode_GetNext().
2595
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002596 On input pItemArray contains a list of labels and data types
2597 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002598
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002599 On output the fully retrieved items are filled in with
2600 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002601
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002602 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002603 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002604static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002605MapSearch(QCBORDecodeContext *pMe,
2606 QCBORItem *pItemArray,
2607 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002608 void *pCBContext,
2609 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002610{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002611 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002612 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002613
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002614 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002615 uReturn = pMe->uLastError;
2616 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002617 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002618
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002619 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002620 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2621 /* QCBOR_TYPE_NONE as first item indicates just looking
2622 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002623 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2624 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002625 }
2626
Laurence Lundblade085d7952020-07-24 10:26:30 -07002627 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2628 // It is an empty bounded array or map
2629 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2630 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002631 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002632 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002633 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002634 // Nothing is ever found in an empty array or map. All items
2635 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002636 uReturn = QCBOR_SUCCESS;
2637 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002638 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002639 }
2640
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002641 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002642 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2643
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002644 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002645 UsefulInputBuf_Seek(&(pMe->InBuf),
2646 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002647
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002648 /*
2649 Loop over all the items in the map. They could be
2650 deeply nested and this should handle both definite
2651 and indefinite length maps and arrays, so this
2652 adds some complexity.
2653 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002654 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002655 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002656 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002657 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002658 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002659
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002660 /* Get the item */
2661 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002662 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002663 if(QCBORDecode_IsNotWellFormed(uReturn)) {
2664 /* Got non-well-formed CBOR so map can't even be decoded. */
Laurence Lundblade4b270642020-08-14 12:53:07 -07002665 // TODO: also bail out on implementation limits like array too big
Laurence Lundblade1341c592020-04-11 14:19:05 -07002666 goto Done;
2667 }
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002668 if(uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
2669 // Unexpected end of map or array.
2670 goto Done;
2671 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002672
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002673 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002674 bool bMatched = false;
2675 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
Laurence Lundblade4b270642020-08-14 12:53:07 -07002676 // TODO: have label filled in on invalid CBOR so error reporting
Laurence Lundblade9b334962020-08-27 10:55:53 -07002677 // can work a lot better.
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002678 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002679 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002680 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2681 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002682 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002683 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002684 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002685 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002686 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002687 goto Done;
2688 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002689
Laurence Lundblade1341c592020-04-11 14:19:05 -07002690 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002691 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002692 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002693 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002694 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002695 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002696 bMatched = true;
2697 }
2698 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002699
2700
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002701 if(!bMatched && pfCallback != NULL) {
2702 /*
2703 Call the callback on unmatched labels.
2704 (It is tempting to do duplicate detection here, but that would
2705 require dynamic memory allocation because the number of labels
2706 that might be encountered is unbounded.)
2707 */
2708 uReturn = (*pfCallback)(pCBContext, &Item);
2709 if(uReturn != QCBOR_SUCCESS) {
2710 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002711 }
2712 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002713
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002714 /*
2715 Consume the item whether matched or not. This
2716 does the work of traversing maps and array and
2717 everything in them. In this loop only the
2718 items at the current nesting level are examined
2719 to match the labels.
2720 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002721 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002722 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002723 goto Done;
2724 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002725
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002726 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002727
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002728 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002729
2730 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002731 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2732 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002733
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002734 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002735 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2736
2737 Done2:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002738 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
2739 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002740 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002741 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002742 }
2743 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002744
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002745 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002746}
2747
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002748
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*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002752void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2753 int64_t nLabel,
2754 uint8_t uQcborType,
2755 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002756{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002757 if(pMe->uLastError != QCBOR_SUCCESS) {
2758 return;
2759 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002760
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002761 QCBORItem OneItemSeach[2];
2762 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2763 OneItemSeach[0].label.int64 = nLabel;
2764 OneItemSeach[0].uDataType = uQcborType;
2765 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002766
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002767 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2768 if(uReturn != QCBOR_SUCCESS) {
2769 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002770 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002771 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002772 uReturn = QCBOR_ERR_NOT_FOUND;
2773 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002774 }
2775
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002776 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002777
2778 Done:
2779 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002780}
2781
2782
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002783/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002784 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002785*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002786void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2787 const char *szLabel,
2788 uint8_t uQcborType,
2789 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002790{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002791 if(pMe->uLastError != QCBOR_SUCCESS) {
2792 return;
2793 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002794
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002795 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002796 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2797 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2798 OneItemSeach[0].uDataType = uQcborType;
2799 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002800
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002801 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2802 if(uReturn != QCBOR_SUCCESS) {
2803 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002804 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002805 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002806 uReturn = QCBOR_ERR_NOT_FOUND;
2807 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002808 }
2809
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002810 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002811
2812Done:
2813 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002814}
2815
2816
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002817
Laurence Lundblade9b334962020-08-27 10:55:53 -07002818static QCBORError CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002819{
2820 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2821 if(uDataType == puTypeList[i]) {
2822 return QCBOR_SUCCESS;
2823 }
2824 }
2825 return QCBOR_ERR_UNEXPECTED_TYPE;
2826}
2827
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002828
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002829/**
2830 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002831 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002832
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002833 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2834 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002835
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002836 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2837 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002838static QCBORError CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002839{
2840 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2841 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2842 /* There are tags that QCBOR couldn't process on this item and
2843 the caller has told us there should not be. */
2844 return QCBOR_ERR_UNEXPECTED_TYPE;
2845 }
2846
2847 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2848 const int nItemType = pItem->uDataType;
2849
2850 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2851 // Must match the tag and only the tag
2852 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2853 }
2854
2855 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2856 if(uReturn == QCBOR_SUCCESS) {
2857 return QCBOR_SUCCESS;
2858 }
2859
2860 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2861 /* Must match the content type and only the content type.
2862 There was no match just above so it is a fail. */
2863 return QCBOR_ERR_UNEXPECTED_TYPE;
2864 }
2865
2866 /* If here it can match either the tag or the content
2867 and it hasn't matched the content, so the end
2868 result is whether it matches the tag. This is
2869 also the case that the CBOR standard discourages. */
2870
2871 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2872}
2873
Laurence Lundblade9b334962020-08-27 10:55:53 -07002874
Laurence Lundblade9b334962020-08-27 10:55:53 -07002875
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002876// This could be semi-private if need be
2877static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002878void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2879 int64_t nLabel,
2880 TagSpecification TagSpec,
2881 QCBORItem *pItem)
2882{
2883 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2884 if(pMe->uLastError != QCBOR_SUCCESS) {
2885 return;
2886 }
2887
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002888 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002889}
2890
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002891
2892// This could be semi-private if need be
2893static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002894void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2895 const char *szLabel,
2896 TagSpecification TagSpec,
2897 QCBORItem *pItem)
2898{
2899 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2900 if(pMe->uLastError != QCBOR_SUCCESS) {
2901 return;
2902 }
2903
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002904 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002905}
2906
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002907// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002908void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2909 int64_t nLabel,
2910 TagSpecification TagSpec,
2911 UsefulBufC *pString)
2912{
2913 QCBORItem Item;
2914 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2915 if(pMe->uLastError == QCBOR_SUCCESS) {
2916 *pString = Item.val.string;
2917 }
2918}
2919
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002920// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002921void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2922 const char * szLabel,
2923 TagSpecification TagSpec,
2924 UsefulBufC *pString)
2925{
2926 QCBORItem Item;
2927 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2928 if(pMe->uLastError == QCBOR_SUCCESS) {
2929 *pString = Item.val.string;
2930 }
2931}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002932
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002933/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002934 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002935*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002936QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2937{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002938 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002939}
2940
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002941/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002942 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002943*/
2944QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2945 QCBORItem *pItemList,
2946 void *pCallbackCtx,
2947 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002948{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002949 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002950}
2951
2952
Laurence Lundblade34691b92020-05-18 22:25:25 -07002953static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002954{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002955 // TODO: check that only one item is in pSearch?
Laurence Lundblade34691b92020-05-18 22:25:25 -07002956 if(pMe->uLastError != QCBOR_SUCCESS) {
2957 // Already in error state; do nothing.
2958 return;
2959 }
2960
2961 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002962 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002963 if(pMe->uLastError != QCBOR_SUCCESS) {
2964 return;
2965 }
2966
Laurence Lundblade9b334962020-08-27 10:55:53 -07002967 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
2968 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
2969 return;
2970 }
2971
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002972 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002973 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002974
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002975 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002976 be at the right place.
2977
2978 The UsefulInBuf offset could be anywhere, so no assumption is
2979 made about it.
2980
2981 No assumption is made about the pre-order nesting level either.
2982
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002983 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002984 the map level that is being entered.
2985 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002986 /* Seek to the data item that is the map or array */
2987 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002988
2989 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002990
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002991 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002992}
2993
2994
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002995/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002996 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002997*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002998void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002999{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003000 QCBORItem OneItemSeach[2];
3001 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3002 OneItemSeach[0].label.int64 = nLabel;
3003 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3004 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003005
Laurence Lundblade9b334962020-08-27 10:55:53 -07003006 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003007 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003008}
3009
3010
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003011/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003012 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003013*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003014void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003015{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003016 QCBORItem OneItemSeach[2];
3017 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3018 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3019 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3020 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003021
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003022 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003023}
3024
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003025/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003026 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003027*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003028void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003029{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003030 QCBORItem OneItemSeach[2];
3031 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3032 OneItemSeach[0].label.int64 = nLabel;
3033 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3034 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003035
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003036 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003037}
3038
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003039/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003040 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003041*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003042void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3043{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003044 QCBORItem OneItemSeach[2];
3045 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3046 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3047 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3048 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003049
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003050 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003051}
3052
3053
Laurence Lundblade02625d42020-06-25 14:41:41 -07003054// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003055void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003056{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003057 QCBORError uErr;
3058
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003059 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003060 if(pMe->uLastError != QCBOR_SUCCESS) {
3061 // Already in error state; do nothing.
3062 return;
3063 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003064
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003065 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003066 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003067 uErr = QCBORDecode_GetNext(pMe, &Item);
3068 if(uErr != QCBOR_SUCCESS) {
3069 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003070 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003071 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003072 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3073 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003074 }
3075
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003076 CopyTags(pMe, &Item);
3077
3078
Laurence Lundbladef0499502020-08-01 11:55:57 -07003079 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003080 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003081 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3082 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003083 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003084 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3085 }
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003086 // Special case to increment nesting level for zero-length maps and arrays entered in bounded mode.
3087 DecodeNesting_Descend(&(pMe->nesting), uType);
3088 }
3089
Laurence Lundblade02625d42020-06-25 14:41:41 -07003090 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003091
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003092 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3093 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003094
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003095Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003096 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003097}
3098
Laurence Lundblade02625d42020-06-25 14:41:41 -07003099
3100/*
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003101 This is the common work for exiting a level that is a bounded map, array or bstr
3102 wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003103
3104 One chunk of work is to set up the pre-order traversal so it is at
3105 the item just after the bounded map, array or bstr that is being
3106 exited. This is somewhat complex.
3107
3108 The other work is to level-up the bounded mode to next higest bounded
3109 mode or the top level if there isn't one.
3110 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003111static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003112ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003113{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003114 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003115
Laurence Lundblade02625d42020-06-25 14:41:41 -07003116 /*
3117 First the pre-order-traversal byte offset is positioned to the
3118 item just after the bounded mode item that was just consumed.
3119 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003120 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3121
Laurence Lundblade02625d42020-06-25 14:41:41 -07003122 /*
3123 Next, set the current nesting level to one above the bounded level
3124 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003125
Laurence Lundblade02625d42020-06-25 14:41:41 -07003126 DecodeNesting_CheckBoundedType() is always called before this and
3127 makes sure pCurrentBounded is valid.
3128 */
3129 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3130
3131 /*
3132 This does the complex work of leveling up the pre-order traversal
3133 when the end of a map or array or another bounded level is
3134 reached. It may do nothing, or ascend all the way to the top
3135 level.
3136 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003137 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003138 if(uErr != QCBOR_SUCCESS) {
3139 goto Done;
3140 }
3141
Laurence Lundblade02625d42020-06-25 14:41:41 -07003142 /*
3143 This makes the next highest bounded level the current bounded
3144 level. If there is no next highest level, then no bounded mode is
3145 in effect.
3146 */
3147 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003148
Laurence Lundblade02625d42020-06-25 14:41:41 -07003149 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003150
3151Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07003152 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003153 return uErr;
3154}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003155
Laurence Lundblade02625d42020-06-25 14:41:41 -07003156
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003157// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003158void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003159{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003160 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003161 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003162 return;
3163 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003164
Laurence Lundblade02625d42020-06-25 14:41:41 -07003165 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003166
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003167 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003168 uErr = QCBOR_ERR_CLOSE_MISMATCH;
3169 goto Done;
3170 }
3171
Laurence Lundblade02625d42020-06-25 14:41:41 -07003172 /*
3173 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003174 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003175 from previous map search, then do a dummy search.
3176 */
3177 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003178 QCBORItem Dummy;
3179 Dummy.uLabelType = QCBOR_TYPE_NONE;
3180 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3181 if(uErr != QCBOR_SUCCESS) {
3182 goto Done;
3183 }
3184 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003185
Laurence Lundblade02625d42020-06-25 14:41:41 -07003186 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003187
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003188Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003189 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003190}
3191
3192
Laurence Lundblade1341c592020-04-11 14:19:05 -07003193
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003194static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003195 const QCBORItem *pItem,
3196 uint8_t uTagRequirement,
3197 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003198{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003199 if(pBstr) {
3200 *pBstr = NULLUsefulBufC;
3201 }
3202
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003203 if(pMe->uLastError != QCBOR_SUCCESS) {
3204 // Already in error state; do nothing.
3205 return pMe->uLastError;
3206 }
3207
3208 QCBORError uError = QCBOR_SUCCESS;
3209
3210 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3211 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3212 goto Done;;
3213 }
3214
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003215 const TagSpecification TagSpec =
3216 {
3217 uTagRequirement,
3218 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3219 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3220 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003221
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003222 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003223 if(uError != QCBOR_SUCCESS) {
3224 goto Done;
3225 }
3226
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003227 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003228 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07003229 so the increment in NestLevelAscender called by ExitBoundedLevel()
3230 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003231 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003232 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003233
3234 if(pBstr) {
3235 *pBstr = pItem->val.string;
3236 }
3237
3238 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003239
3240 // Need to move UIB input cursor to the right place
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003241 // Most of these calls are simple inline accessors so this doesn't
3242 // amount to much code. There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003243 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003244 if(uEndOfBstr >= UINT32_MAX || uPreviousLength >= UINT32_MAX) {
3245 // TODO: test this error condition
3246 uError = QCBOR_ERR_BUFFER_TOO_LARGE;
3247 goto Done;
3248 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003249 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003250 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003251
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003252 // Casts are OK because of the checks above.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003253 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003254 (uint32_t)uPreviousLength,
3255 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003256Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07003257 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003258
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003259 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003260}
3261
3262
Laurence Lundblade02625d42020-06-25 14:41:41 -07003263/*
3264 Public function, see header qcbor/qcbor_decode.h file
3265 */
3266void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003267 uint8_t uTagRequirement,
3268 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003269{
3270 if(pMe->uLastError != QCBOR_SUCCESS) {
3271 // Already in error state; do nothing.
3272 return;
3273 }
3274
3275 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003276 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003277 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3278 if(pMe->uLastError != QCBOR_SUCCESS) {
3279 return;
3280 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003281
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003282 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003283 &Item,
3284 uTagRequirement,
3285 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003286}
3287
3288
Laurence Lundblade02625d42020-06-25 14:41:41 -07003289/*
3290 Public function, see header qcbor/qcbor_decode.h file
3291 */
3292void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003293 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003294 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003295 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003296{
3297 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003298 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003299
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003300 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003301}
3302
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003303
Laurence Lundblade02625d42020-06-25 14:41:41 -07003304/*
3305 Public function, see header qcbor/qcbor_decode.h file
3306 */
3307void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003308 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003309 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003310 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003311{
3312 QCBORItem Item;
3313 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3314
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003315 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003316}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003317
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003318
Laurence Lundblade02625d42020-06-25 14:41:41 -07003319/*
3320 Public function, see header qcbor/qcbor_decode.h file
3321 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003322void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003323{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003324 if(pMe->uLastError != QCBOR_SUCCESS) {
3325 // Already in error state; do nothing.
3326 return;
3327 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003328
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003329 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003330 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3331 return;
3332 }
3333
3334 /*
3335 Reset the length of the UsefulInputBuf to what it was before
3336 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003337 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003338 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3339 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003340
3341
Laurence Lundblade02625d42020-06-25 14:41:41 -07003342 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003343 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003344}
3345
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003346
Laurence Lundbladee6430642020-03-14 21:15:44 -07003347
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003348
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003349
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003350
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003351
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003352
Laurence Lundblade9b334962020-08-27 10:55:53 -07003353static QCBORError InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003354{
3355 switch(pItem->uDataType) {
3356 case QCBOR_TYPE_TRUE:
3357 *pBool = true;
3358 return QCBOR_SUCCESS;
3359 break;
3360
3361 case QCBOR_TYPE_FALSE:
3362 *pBool = false;
3363 return QCBOR_SUCCESS;
3364 break;
3365
3366 default:
3367 return QCBOR_ERR_UNEXPECTED_TYPE;
3368 break;
3369 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003370 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003371}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003372
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003373
Laurence Lundblade9b334962020-08-27 10:55:53 -07003374
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003375/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003376 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003377*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003378void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003379{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003380 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003381 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003382 return;
3383 }
3384
Laurence Lundbladec4537442020-04-14 18:53:22 -07003385 QCBORError nError;
3386 QCBORItem Item;
3387
3388 nError = QCBORDecode_GetNext(pMe, &Item);
3389 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003390 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003391 return;
3392 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003393 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003394}
3395
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003396
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003397/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003398 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003399*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003400void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003401{
3402 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003403 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003404
Laurence Lundblade9b334962020-08-27 10:55:53 -07003405 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003406}
3407
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003408
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003409/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003410 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003411*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003412void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3413{
3414 QCBORItem Item;
3415 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3416
Laurence Lundblade9b334962020-08-27 10:55:53 -07003417 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003418}
3419
3420
3421
Laurence Lundblade9b334962020-08-27 10:55:53 -07003422/*
3423 A number of methods decode CBOR that is associated with a
3424 specific tag or tags.
Laurence Lundbladec7114722020-08-13 05:11:40 -07003425
Laurence Lundblade9b334962020-08-27 10:55:53 -07003426 The API of the method returns the
3427 data in a way specific to the
3428
3429 No tags at all.
3430
3431
3432 Require tag for the particular type for the method and no other.
3433
3434
3435 Either no tags at all or the particular type for the method and no other.
3436
3437 No tag for particular type; pass other tags along.
3438
3439 Require the tag for the particular type; pass other tags along
3440
3441 Any tagging is OK; consume the tag for the particular type if present,
3442 pass other tags along.
3443
3444
3445 1) REQUIRED
3446- 1 XXXX -- works
3447- T 1 XXX -- works, T is returned
3448
3449 if(tag is of interest) {
3450 process content
3451 return T if present
3452 }
3453
3454
3455 2) FORBIDDEN
3456 - XXX -- works
3457 - T XXX -- ???
3458
3459 if(tag is of interest) {
3460 error out since tag is forbidden
3461 } else {
3462 process contents
3463 return T
3464 }
3465
3466 3) OPTIONAL
3467 - XXX works
3468 - 1 XXX works
3469 - T XXX
3470 - T 1 XXX works, T is returned
3471
3472if (inner tag is of interest) {
3473 process content
3474 return tag T if present
3475 } else if (there is no tag) {
3476 process content
3477 } else {
3478 process content if possible
3479 return T
3480 }
3481
3482A field is type X
3483 - tag for type X is REQUIRED
3484 - tag for type X is FORBIDDEN
3485 - tag for type X is optional
3486 - Other tags are FORBIDDEN
3487 - Other tags are ALLOWED
3488
3489
3490
3491 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003492
3493static void ProcessEpochDate(QCBORDecodeContext *pMe,
3494 QCBORItem *pItem,
3495 uint8_t uTagRequirement,
3496 int64_t *pnTime)
3497{
3498 if(pMe->uLastError != QCBOR_SUCCESS) {
3499 // Already in error state, do nothing
3500 return;
3501 }
3502
3503 QCBORError uErr;
3504
3505 const TagSpecification TagSpec =
3506 {
3507 uTagRequirement,
3508 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3509 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT}
3510 };
3511
Laurence Lundblade4b270642020-08-14 12:53:07 -07003512 // TODO: this will give an unexpected type error instead of
Laurence Lundbladec7114722020-08-13 05:11:40 -07003513 // overflow error for QCBOR_TYPE_UINT64 because TagSpec
3514 // only has three target types.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003515 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003516 if(uErr != QCBOR_SUCCESS) {
3517 goto Done;
3518 }
3519
3520 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3521 uErr = DecodeDateEpoch(pItem);
3522 if(uErr != QCBOR_SUCCESS) {
3523 goto Done;
3524 }
3525 }
3526
Laurence Lundblade9b334962020-08-27 10:55:53 -07003527 // Save the tags in the last item's tags in the decode context
3528 // for QCBORDecode_GetNthTagOfLast()
3529 CopyTags(pMe, pItem);
3530
Laurence Lundbladec7114722020-08-13 05:11:40 -07003531 *pnTime = pItem->val.epochDate.nSeconds;
3532
3533Done:
3534 pMe->uLastError = (uint8_t)uErr;
3535}
3536
3537
3538void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
3539 uint8_t uTagRequirement,
3540 int64_t *pnTime)
3541{
3542 if(pMe->uLastError != QCBOR_SUCCESS) {
3543 // Already in error state, do nothing
3544 return;
3545 }
3546
3547 QCBORItem Item;
3548 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3549
3550 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3551}
3552
3553
3554void
3555QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3556 int64_t nLabel,
3557 uint8_t uTagRequirement,
3558 int64_t *pnTime)
3559{
3560 QCBORItem Item;
3561 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3562 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3563}
3564
3565
3566void
3567QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3568 const char *szLabel,
3569 uint8_t uTagRequirement,
3570 int64_t *pnTime)
3571{
3572 QCBORItem Item;
3573 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3574 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3575}
3576
3577
3578
3579
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003580void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3581 TagSpecification TagSpec,
3582 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003583{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003584 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003585 // Already in error state, do nothing
3586 return;
3587 }
3588
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003589 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003590 QCBORItem Item;
3591
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003592 uError = QCBORDecode_GetNext(pMe, &Item);
3593 if(uError != QCBOR_SUCCESS) {
3594 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003595 return;
3596 }
3597
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003598 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003599
3600 if(pMe->uLastError == QCBOR_SUCCESS) {
3601 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003602 } else {
3603 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003604 }
3605}
3606
Laurence Lundbladec4537442020-04-14 18:53:22 -07003607
3608
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003609
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003610static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003611 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003612 UsefulBufC *pValue,
3613 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003614{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003615 const TagSpecification TagSpec =
3616 {
3617 uTagRequirement,
3618 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3619 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3620 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003621
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003622 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003623 if(uErr != QCBOR_SUCCESS) {
3624 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003625 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003626
3627 *pValue = pItem->val.string;
3628
3629 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3630 *pbIsNegative = false;
3631 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3632 *pbIsNegative = true;
3633 }
3634
3635 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003636}
3637
3638
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003639/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003640 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003641 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003642void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3643 uint8_t uTagRequirement,
3644 UsefulBufC *pValue,
3645 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003646{
3647 if(pMe->uLastError != QCBOR_SUCCESS) {
3648 // Already in error state, do nothing
3649 return;
3650 }
3651
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003652 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003653 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3654 if(uError != QCBOR_SUCCESS) {
3655 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003656 return;
3657 }
3658
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003659 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003660}
3661
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003662
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003663/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003664 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003665*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003666void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3667 int64_t nLabel,
3668 uint8_t uTagRequirement,
3669 UsefulBufC *pValue,
3670 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003671{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003672 QCBORItem Item;
3673 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003674 if(pMe->uLastError != QCBOR_SUCCESS) {
3675 return;
3676 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003677
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003678 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003679}
3680
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003681
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003682/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003683 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003684*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003685void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3686 const char *szLabel,
3687 uint8_t uTagRequirement,
3688 UsefulBufC *pValue,
3689 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003690{
3691 QCBORItem Item;
3692 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003693 if(pMe->uLastError != QCBOR_SUCCESS) {
3694 return;
3695 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003696
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003697 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003698}
3699
3700
3701
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003702
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003703// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003704QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3705 const QCBORItem *pItem,
3706 UsefulBufC *pMessage,
3707 bool *pbIsNot7Bit)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003708{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003709 const TagSpecification TagSpecText =
3710 {
3711 uTagRequirement,
3712 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3713 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3714 };
3715 const TagSpecification TagSpecBinary =
3716 {
3717 uTagRequirement,
3718 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3719 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3720 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003721
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003722 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003723
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003724 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003725 *pMessage = pItem->val.string;
3726 if(pbIsNot7Bit != NULL) {
3727 *pbIsNot7Bit = false;
3728 }
3729 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003730 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003731 *pMessage = pItem->val.string;
3732 if(pbIsNot7Bit != NULL) {
3733 *pbIsNot7Bit = true;
3734 }
3735 uReturn = QCBOR_SUCCESS;
3736
3737 } else {
3738 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3739 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003740
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003741 return uReturn;
3742}
3743
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003744// Improvement: add methods for wrapped CBOR, a simple alternate to EnterBstrWrapped
3745
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003746
3747
3748
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003749#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003750
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003751typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003752
3753
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003754// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003755static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003756{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003757 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003758
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003759 if(uResult != 0) {
3760 /* This loop will run a maximum of 19 times because
3761 * UINT64_MAX < 10 ^^ 19. More than that will cause
3762 * exit with the overflow error
3763 */
3764 for(; nExponent > 0; nExponent--) {
3765 if(uResult > UINT64_MAX / 10) {
3766 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3767 }
3768 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003769 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003770
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003771 for(; nExponent < 0; nExponent++) {
3772 uResult = uResult / 10;
3773 if(uResult == 0) {
3774 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3775 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003776 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003777 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003778 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003779
3780 *puResult = uResult;
3781
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003782 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003783}
3784
3785
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003786// The exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003787static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003788{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003789 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003790
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003791 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003792
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003793 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003794 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003795 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003796 */
3797 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003798 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003799 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003800 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003801 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003802 nExponent--;
3803 }
3804
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003805 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003806 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003807 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3808 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003809 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003810 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003811 }
3812
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003813 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003814
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003815 return QCBOR_SUCCESS;
3816}
3817
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003818
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003819/*
3820 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3821 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003822static inline QCBORError ExponentiateNN(int64_t nMantissa,
3823 int64_t nExponent,
3824 int64_t *pnResult,
3825 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003826{
3827 uint64_t uResult;
3828
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003829 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003830 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003831 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3832
3833 // Do the exponentiation of the positive mantissa
3834 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3835 if(uReturn) {
3836 return uReturn;
3837 }
3838
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003839
Laurence Lundblade983500d2020-05-14 11:49:34 -07003840 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3841 of INT64_MIN. This assumes two's compliment representation where
3842 INT64_MIN is one increment farther from 0 than INT64_MAX.
3843 Trying to write -INT64_MIN doesn't work to get this because the
3844 compiler tries to work with an int64_t which can't represent
3845 -INT64_MIN.
3846 */
3847 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3848
3849 // Error out if too large
3850 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003851 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3852 }
3853
3854 // Casts are safe because of checks above
3855 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3856
3857 return QCBOR_SUCCESS;
3858}
3859
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003860
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003861/*
3862 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3863 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003864static inline QCBORError ExponentitateNU(int64_t nMantissa,
3865 int64_t nExponent,
3866 uint64_t *puResult,
3867 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003868{
3869 if(nMantissa < 0) {
3870 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3871 }
3872
3873 // Cast to unsigned is OK because of check for negative
3874 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3875 // Exponentiation is straight forward
3876 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3877}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003878
3879
3880/*
3881 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3882 */
3883static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3884 int64_t nExponent,
3885 uint64_t *puResult,
3886 fExponentiator pfExp)
3887{
3888 return (*pfExp)(uMantissa, nExponent, puResult);
3889}
3890
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003891#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3892
3893
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003894
3895
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003896
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003897static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003898{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003899 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003900
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003901 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003902 const uint8_t *pByte = BigNum.ptr;
3903 size_t uLen = BigNum.len;
3904 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003905 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003906 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003907 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003908 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003909 }
3910
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003911 *pResult = uResult;
3912 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003913}
3914
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003915
Laurence Lundblade887add82020-05-17 05:50:34 -07003916static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003917{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003918 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003919}
3920
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003921
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003922static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003923{
3924 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003925 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3926 if(uError) {
3927 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003928 }
3929 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3930 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003931 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003932}
3933
3934
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003935static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003936{
3937 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003938 /* The negative integer furthest from zero for a C int64_t is
3939 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3940 negative number in CBOR is computed as -n - 1 where n is the
3941 encoded integer, where n is what is in the variable BigNum. When
3942 converting BigNum to a uint64_t, the maximum value is thus
3943 INT64_MAX, so that when it -n - 1 is applied to it the result will
3944 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003945
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003946 -n - 1 <= INT64_MIN.
3947 -n - 1 <= -INT64_MAX - 1
3948 n <= INT64_MAX.
3949 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003950 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003951 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003952 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003953 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003954
3955 /// Now apply -n - 1. The cast is safe because
3956 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3957 // is the largest positive integer that an int64_t can
3958 // represent. */
3959 *pnResult = -(int64_t)uResult - 1;
3960
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003961 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003962}
3963
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003964
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003965
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003966
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003967
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003968/*
3969Convert a integers and floats to an int64_t.
3970
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003971\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003972
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003973\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003974
3975\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3976
3977\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3978
3979*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003980static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003981{
3982 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003983 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003984 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003985#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003986 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003987 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3988 http://www.cplusplus.com/reference/cmath/llround/
3989 */
3990 // Not interested in FE_INEXACT
3991 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003992 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3993 *pnValue = llround(pItem->val.dfnum);
3994 } else {
3995 *pnValue = lroundf(pItem->val.fnum);
3996 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003997 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
3998 // llround() shouldn't result in divide by zero, but catch
3999 // it here in case it unexpectedly does. Don't try to
4000 // distinguish between the various exceptions because it seems
4001 // they vary by CPU, compiler and OS.
4002 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004003 }
4004 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004005 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004006 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004007#else
4008 return QCBOR_ERR_HW_FLOAT_DISABLED;
4009#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004010 break;
4011
4012 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004013 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004014 *pnValue = pItem->val.int64;
4015 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004016 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004017 }
4018 break;
4019
4020 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004021 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004022 if(pItem->val.uint64 < INT64_MAX) {
4023 *pnValue = pItem->val.int64;
4024 } else {
4025 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4026 }
4027 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004028 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004029 }
4030 break;
4031
4032 default:
4033 return QCBOR_ERR_UNEXPECTED_TYPE;
4034 }
4035 return QCBOR_SUCCESS;
4036}
4037
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004038
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004039void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004040 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004041 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004042 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004043{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004044 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004045 return;
4046 }
4047
Laurence Lundbladee6430642020-03-14 21:15:44 -07004048 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004049 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4050 if(uError) {
4051 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004052 return;
4053 }
4054
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004055 if(pItem) {
4056 *pItem = Item;
4057 }
4058
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004059 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004060}
4061
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004062
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004063void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4064 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004065 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004066 int64_t *pnValue,
4067 QCBORItem *pItem)
4068{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004069 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004070 if(pMe->uLastError != QCBOR_SUCCESS) {
4071 return;
4072 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004073
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004074 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004075}
4076
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004077
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004078void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4079 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004080 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004081 int64_t *pnValue,
4082 QCBORItem *pItem)
4083{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004084 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004085 if(pMe->uLastError != QCBOR_SUCCESS) {
4086 return;
4087 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004088
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004089 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004090}
4091
4092
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004093/*
4094 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004095
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004096 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004097
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004098 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004099
4100 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4101
4102 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
4103
4104 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004105static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004106{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004107 switch(pItem->uDataType) {
4108
4109 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004110 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004111 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004112 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004113 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004114 }
4115 break;
4116
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004117 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004118 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004119 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004120 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004121 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004122 }
4123 break;
4124
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004125#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4126 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004127 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004128 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004129 pItem->val.expAndMantissa.nExponent,
4130 pnValue,
4131 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004132 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004133 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004134 }
4135 break;
4136
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004137 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004138 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004139 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004140 pItem->val.expAndMantissa.nExponent,
4141 pnValue,
4142 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004143 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004144 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004145 }
4146 break;
4147
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004148 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004149 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004150 int64_t nMantissa;
4151 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004152 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4153 if(uErr) {
4154 return uErr;
4155 }
4156 return ExponentiateNN(nMantissa,
4157 pItem->val.expAndMantissa.nExponent,
4158 pnValue,
4159 Exponentitate10);
4160 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004161 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004162 }
4163 break;
4164
4165 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004166 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004167 int64_t nMantissa;
4168 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004169 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4170 if(uErr) {
4171 return uErr;
4172 }
4173 return ExponentiateNN(nMantissa,
4174 pItem->val.expAndMantissa.nExponent,
4175 pnValue,
4176 Exponentitate10);
4177 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004178 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004179 }
4180 break;
4181
4182 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004183 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004184 int64_t nMantissa;
4185 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004186 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4187 if(uErr) {
4188 return uErr;
4189 }
4190 return ExponentiateNN(nMantissa,
4191 pItem->val.expAndMantissa.nExponent,
4192 pnValue,
4193 Exponentitate2);
4194 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004195 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004196 }
4197 break;
4198
4199 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004200 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004201 int64_t nMantissa;
4202 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004203 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4204 if(uErr) {
4205 return uErr;
4206 }
4207 return ExponentiateNN(nMantissa,
4208 pItem->val.expAndMantissa.nExponent,
4209 pnValue,
4210 Exponentitate2);
4211 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004212 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004213 }
4214 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004215#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4216
Laurence Lundbladee6430642020-03-14 21:15:44 -07004217
Laurence Lundbladec4537442020-04-14 18:53:22 -07004218 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004219 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004220}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004221
4222
Laurence Lundbladec4537442020-04-14 18:53:22 -07004223/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004224 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004225 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004226void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004227{
4228 QCBORItem Item;
4229
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004230 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004231
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004232 if(pMe->uLastError == QCBOR_SUCCESS) {
4233 // The above conversion succeeded
4234 return;
4235 }
4236
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004237 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004238 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004239 return;
4240 }
4241
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004242 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004243}
4244
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004245
4246/*
4247Public function, see header qcbor/qcbor_decode.h file
4248*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004249void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4250 int64_t nLabel,
4251 uint32_t uConvertTypes,
4252 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004253{
4254 QCBORItem Item;
4255
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004256 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004257
4258 if(pMe->uLastError == QCBOR_SUCCESS) {
4259 // The above conversion succeeded
4260 return;
4261 }
4262
4263 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4264 // The above conversion failed in a way that code below can't correct
4265 return;
4266 }
4267
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004268 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004269}
4270
4271
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004272/*
4273Public function, see header qcbor/qcbor_decode.h file
4274*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004275void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4276 const char *szLabel,
4277 uint32_t uConvertTypes,
4278 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004279{
4280 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004281 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004282
4283 if(pMe->uLastError == QCBOR_SUCCESS) {
4284 // The above conversion succeeded
4285 return;
4286 }
4287
4288 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4289 // The above conversion failed in a way that code below can't correct
4290 return;
4291 }
4292
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004293 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004294}
4295
4296
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004297static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004298{
4299 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004300 case QCBOR_TYPE_DOUBLE:
4301 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004302#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004303 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004304 // Can't use llround here because it will not convert values
4305 // greater than INT64_MAX and less than UINT64_MAX that
4306 // need to be converted so it is more complicated.
4307 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4308 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4309 if(isnan(pItem->val.dfnum)) {
4310 return QCBOR_ERR_FLOAT_EXCEPTION;
4311 } else if(pItem->val.dfnum < 0) {
4312 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4313 } else {
4314 double dRounded = round(pItem->val.dfnum);
4315 // See discussion in DecodeDateEpoch() for
4316 // explanation of - 0x7ff
4317 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4318 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4319 }
4320 *puValue = (uint64_t)dRounded;
4321 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004322 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004323 if(isnan(pItem->val.fnum)) {
4324 return QCBOR_ERR_FLOAT_EXCEPTION;
4325 } else if(pItem->val.fnum < 0) {
4326 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4327 } else {
4328 float fRounded = roundf(pItem->val.fnum);
4329 // See discussion in DecodeDateEpoch() for
4330 // explanation of - 0x7ff
4331 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4332 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4333 }
4334 *puValue = (uint64_t)fRounded;
4335 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004336 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004337 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4338 // round() and roundf() shouldn't result in exceptions here, but
4339 // catch them to be robust and thorough. Don't try to
4340 // distinguish between the various exceptions because it seems
4341 // they vary by CPU, compiler and OS.
4342 return QCBOR_ERR_FLOAT_EXCEPTION;
4343 }
4344
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004345 } else {
4346 return QCBOR_ERR_UNEXPECTED_TYPE;
4347 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004348#else
4349 return QCBOR_ERR_HW_FLOAT_DISABLED;
4350#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004351 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004352
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004353 case QCBOR_TYPE_INT64:
4354 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4355 if(pItem->val.int64 >= 0) {
4356 *puValue = (uint64_t)pItem->val.int64;
4357 } else {
4358 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4359 }
4360 } else {
4361 return QCBOR_ERR_UNEXPECTED_TYPE;
4362 }
4363 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004364
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004365 case QCBOR_TYPE_UINT64:
4366 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4367 *puValue = pItem->val.uint64;
4368 } else {
4369 return QCBOR_ERR_UNEXPECTED_TYPE;
4370 }
4371 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004372
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004373 default:
4374 return QCBOR_ERR_UNEXPECTED_TYPE;
4375 }
4376
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004377 return QCBOR_SUCCESS;
4378}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004379
4380
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004381void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004382 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004383 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004384 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004385{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004386 if(pMe->uLastError != QCBOR_SUCCESS) {
4387 return;
4388 }
4389
Laurence Lundbladec4537442020-04-14 18:53:22 -07004390 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004391
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004392 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4393 if(uError) {
4394 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004395 return;
4396 }
4397
Laurence Lundbladea826c502020-05-10 21:07:00 -07004398 if(pItem) {
4399 *pItem = Item;
4400 }
4401
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004402 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004403}
4404
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004405
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004406void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004407 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004408 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004409 uint64_t *puValue,
4410 QCBORItem *pItem)
4411{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004412 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004413 if(pMe->uLastError != QCBOR_SUCCESS) {
4414 return;
4415 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004416
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004417 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004418}
4419
4420
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004421void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004422 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004423 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004424 uint64_t *puValue,
4425 QCBORItem *pItem)
4426{
4427 if(pMe->uLastError != QCBOR_SUCCESS) {
4428 return;
4429 }
4430
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004431 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004432 if(pMe->uLastError != QCBOR_SUCCESS) {
4433 return;
4434 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004435
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004436 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004437}
4438
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004439
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004440/*
4441 Public function, see header qcbor/qcbor_decode.h file
4442*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004443static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004444{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004445 switch(pItem->uDataType) {
4446
4447 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004448 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004449 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4450 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004451 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004452 }
4453 break;
4454
4455 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004456 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004457 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4458 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004459 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004460 }
4461 break;
4462
4463#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4464
4465 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004466 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004467 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004468 pItem->val.expAndMantissa.nExponent,
4469 puValue,
4470 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004471 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004472 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004473 }
4474 break;
4475
4476 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004477 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004478 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4479 pItem->val.expAndMantissa.nExponent,
4480 puValue,
4481 Exponentitate2);
4482 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004483 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004484 }
4485 break;
4486
4487 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004488 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004489 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004490 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004491 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004492 if(uErr != QCBOR_SUCCESS) {
4493 return uErr;
4494 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004495 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004496 pItem->val.expAndMantissa.nExponent,
4497 puValue,
4498 Exponentitate10);
4499 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004500 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004501 }
4502 break;
4503
4504 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004505 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004506 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4507 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004508 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004509 }
4510 break;
4511
4512 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004513 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004514 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004515 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004516 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004517 if(uErr != QCBOR_SUCCESS) {
4518 return uErr;
4519 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004520 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004521 pItem->val.expAndMantissa.nExponent,
4522 puValue,
4523 Exponentitate2);
4524 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004525 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004526 }
4527 break;
4528
4529 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004530 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004531 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4532 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004533 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004534 }
4535 break;
4536#endif
4537 default:
4538 return QCBOR_ERR_UNEXPECTED_TYPE;
4539 }
4540}
4541
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004542
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004543/*
4544 Public function, see header qcbor/qcbor_decode.h file
4545*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004546void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004547{
4548 QCBORItem Item;
4549
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004550 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004551
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004552 if(pMe->uLastError == QCBOR_SUCCESS) {
4553 // The above conversion succeeded
4554 return;
4555 }
4556
4557 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4558 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004559 return;
4560 }
4561
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004562 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004563}
4564
Laurence Lundbladec4537442020-04-14 18:53:22 -07004565
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004566/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004567 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004568*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004569void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004570 int64_t nLabel,
4571 uint32_t uConvertTypes,
4572 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004573{
4574 QCBORItem Item;
4575
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004576 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004577
4578 if(pMe->uLastError == QCBOR_SUCCESS) {
4579 // The above conversion succeeded
4580 return;
4581 }
4582
4583 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4584 // The above conversion failed in a way that code below can't correct
4585 return;
4586 }
4587
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004588 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004589}
4590
4591
4592/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004593 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004594*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004595void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004596 const char *szLabel,
4597 uint32_t uConvertTypes,
4598 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004599{
4600 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004601 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004602
4603 if(pMe->uLastError == QCBOR_SUCCESS) {
4604 // The above conversion succeeded
4605 return;
4606 }
4607
4608 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4609 // The above conversion failed in a way that code below can't correct
4610 return;
4611 }
4612
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004613 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004614}
4615
4616
Laurence Lundblade9b334962020-08-27 10:55:53 -07004617static QCBORError ConvertDouble(const QCBORItem *pItem,
4618 uint32_t uConvertTypes,
4619 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004620{
4621 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004622 case QCBOR_TYPE_FLOAT:
4623#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4624 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4625 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004626 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004627 *pdValue = (double)pItem->val.fnum;
4628 } else {
4629 return QCBOR_ERR_UNEXPECTED_TYPE;
4630 }
4631 }
4632#else
4633 return QCBOR_ERR_HW_FLOAT_DISABLED;
4634#endif
4635 break;
4636
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004637 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004638 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4639 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004640 *pdValue = pItem->val.dfnum;
4641 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004642 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004643 }
4644 }
4645 break;
4646
4647 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004648#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004649 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004650 // A simple cast seems to do the job with no worry of exceptions.
4651 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004652 *pdValue = (double)pItem->val.int64;
4653
4654 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004655 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004656 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004657#else
4658 return QCBOR_ERR_HW_FLOAT_DISABLED;
4659#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004660 break;
4661
4662 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004663#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004664 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004665 // A simple cast seems to do the job with no worry of exceptions.
4666 // There will be precision loss for some values.
4667 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004668 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004669 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004670 }
4671 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004672#else
4673 return QCBOR_ERR_HW_FLOAT_DISABLED;
4674#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004675
4676 default:
4677 return QCBOR_ERR_UNEXPECTED_TYPE;
4678 }
4679
4680 return QCBOR_SUCCESS;
4681}
4682
4683
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004684void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004685 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004686 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004687 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004688{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004689 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004690 return;
4691 }
4692
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004693 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004694
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004695 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004696 if(uError) {
4697 pMe->uLastError = (uint8_t)uError;
4698 return;
4699 }
4700
4701 if(pItem) {
4702 *pItem = Item;
4703 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004704
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004705 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004706}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004707
Laurence Lundbladec4537442020-04-14 18:53:22 -07004708
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004709void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4710 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004711 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004712 double *pdValue,
4713 QCBORItem *pItem)
4714{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004715 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004716 if(pMe->uLastError != QCBOR_SUCCESS) {
4717 return;
4718 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004719
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004720 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004721}
4722
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004723
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004724void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4725 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004726 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004727 double *pdValue,
4728 QCBORItem *pItem)
4729{
4730 if(pMe->uLastError != QCBOR_SUCCESS) {
4731 return;
4732 }
4733
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004734 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004735 if(pMe->uLastError != QCBOR_SUCCESS) {
4736 return;
4737 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004738
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004739 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004740}
4741
4742
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004743#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004744static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4745{
4746 double dResult;
4747
4748 dResult = 0.0;
4749 const uint8_t *pByte = BigNum.ptr;
4750 size_t uLen = BigNum.len;
4751 /* This will overflow and become the float value INFINITY if the number
4752 is too large to fit. No error will be logged.
4753 TODO: should an error be logged? */
4754 while(uLen--) {
4755 dResult = (dResult * 256.0) + (double)*pByte++;
4756 }
4757
4758 return dResult;
4759}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004760#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4761
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004762
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004763static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004764{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004765#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004766 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004767 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4768
4769 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004770 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004771
4772#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004773 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004774 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004775 // TODO: rounding and overflow errors
4776 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4777 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4778 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004779 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004780 }
4781 break;
4782
4783 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004784 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004785 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4786 exp2((double)pItem->val.expAndMantissa.nExponent);
4787 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004788 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004789 }
4790 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004791#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004792
4793 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004794 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004795 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4796 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004797 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004798 }
4799 break;
4800
4801 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004802 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004803 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004804 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004805 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004806 }
4807 break;
4808
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004809#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004810 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004811 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004812 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4813 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4814 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004815 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004816 }
4817 break;
4818
4819 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004820 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004821 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4822 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4823 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004824 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004825 }
4826 break;
4827
4828 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004829 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004830 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4831 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4832 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004833 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004834 }
4835 break;
4836
4837 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004838 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004839 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004840 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4841 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004842 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004843 }
4844 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004845#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4846
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004847
4848 default:
4849 return QCBOR_ERR_UNEXPECTED_TYPE;
4850 }
4851
4852 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004853
4854#else
4855 (void)pItem;
4856 (void)uConvertTypes;
4857 (void)pdValue;
4858 return QCBOR_ERR_HW_FLOAT_DISABLED;
4859#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4860
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004861}
4862
4863
4864/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004865 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004866*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004867void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4868 uint32_t uConvertTypes,
4869 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004870{
4871
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004872 QCBORItem Item;
4873
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004874 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004875
4876 if(pMe->uLastError == QCBOR_SUCCESS) {
4877 // The above conversion succeeded
4878 return;
4879 }
4880
4881 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4882 // The above conversion failed in a way that code below can't correct
4883 return;
4884 }
4885
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004886 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004887}
4888
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004889
4890/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004891 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004892*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004893void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4894 int64_t nLabel,
4895 uint32_t uConvertTypes,
4896 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004897{
4898 QCBORItem Item;
4899
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004900 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004901
4902 if(pMe->uLastError == QCBOR_SUCCESS) {
4903 // The above conversion succeeded
4904 return;
4905 }
4906
4907 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4908 // The above conversion failed in a way that code below can't correct
4909 return;
4910 }
4911
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004912 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004913}
4914
4915
4916/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004917 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004918*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004919void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4920 const char *szLabel,
4921 uint32_t uConvertTypes,
4922 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004923{
4924 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004925 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004926
4927 if(pMe->uLastError == QCBOR_SUCCESS) {
4928 // The above conversion succeeded
4929 return;
4930 }
4931
4932 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4933 // The above conversion failed in a way that code below can't correct
4934 return;
4935 }
4936
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004937 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004938}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004939
4940
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004941
4942
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004943#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004944static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4945{
4946 while((uInt & 0xff00000000000000UL) == 0) {
4947 uInt = uInt << 8;
4948 };
4949
4950 UsefulOutBuf UOB;
4951
4952 UsefulOutBuf_Init(&UOB, Buffer);
4953
4954 while(uInt) {
4955 const uint64_t xx = uInt & 0xff00000000000000UL;
4956 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4957 uInt = uInt << 8;
4958 (void)xx;
4959 }
4960
4961 return UsefulOutBuf_OutUBuf(&UOB);
4962}
4963
4964
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004965static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4966 TagSpecification TagSpec,
4967 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004968{
4969 QCBORError uErr;
4970 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004971 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004972 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004973 if(uErr != QCBOR_SUCCESS) {
4974 goto Done;
4975 }
4976
4977 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4978 break; // Successful exit. Moving on to finish decoding.
4979 }
4980
4981 // The item is an array, which means an undecoded
4982 // mantissa and exponent, so decode it. It will then
4983 // have a different type and exit the loop if.
4984 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4985 if(uErr != QCBOR_SUCCESS) {
4986 goto Done;
4987 }
4988
4989 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07004990 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004991 }
4992Done:
4993 return uErr;
4994}
4995
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004996
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004997static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004998 TagSpecification TagSpec,
4999 QCBORItem *pItem,
5000 int64_t *pnMantissa,
5001 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005002{
5003 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005004
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005005 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005006 if(uErr != QCBOR_SUCCESS) {
5007 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005008 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005009
Laurence Lundblade9b334962020-08-27 10:55:53 -07005010 switch (pItem->uDataType) {
5011
5012 case QCBOR_TYPE_DECIMAL_FRACTION:
5013 case QCBOR_TYPE_BIGFLOAT:
5014 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5015 *pnExponent = pItem->val.expAndMantissa.nExponent;
5016 break;
5017
5018 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5019 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5020 *pnExponent = pItem->val.expAndMantissa.nExponent;
5021 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5022 break;
5023
5024 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5025 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5026 *pnExponent = pItem->val.expAndMantissa.nExponent;
5027 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5028 break;
5029
5030 default:
5031 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5032 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005033
5034 Done:
5035 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005036}
5037
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005038
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005039static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005040 TagSpecification TagSpec,
5041 QCBORItem *pItem,
5042 UsefulBuf BufferForMantissa,
5043 UsefulBufC *pMantissa,
5044 bool *pbIsNegative,
5045 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005046{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005047 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005048
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005049 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005050 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005051 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005052 }
5053
5054 uint64_t uMantissa;
5055
5056 switch (pItem->uDataType) {
5057
5058 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005059 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005060 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5061 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5062 *pbIsNegative = false;
5063 } else {
5064 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5065 *pbIsNegative = true;
5066 }
5067 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5068 *pnExponent = pItem->val.expAndMantissa.nExponent;
5069 break;
5070
5071 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005072 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005073 *pnExponent = pItem->val.expAndMantissa.nExponent;
5074 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5075 *pbIsNegative = false;
5076 break;
5077
5078 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005079 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005080 *pnExponent = pItem->val.expAndMantissa.nExponent;
5081 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5082 *pbIsNegative = true;
5083 break;
5084
5085 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005086 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005087 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005088
5089Done:
5090 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005091}
5092
5093
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005094/*
5095 Public function, see header qcbor/qcbor_decode.h file
5096*/
5097void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5098 uint8_t uTagRequirement,
5099 int64_t *pnMantissa,
5100 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005101{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005102 if(pMe->uLastError != QCBOR_SUCCESS) {
5103 return;
5104 }
5105
5106 QCBORItem Item;
5107 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5108 if(uError) {
5109 pMe->uLastError = (uint8_t)uError;
5110 return;
5111 }
5112
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005113 const TagSpecification TagSpec =
5114 {
5115 uTagRequirement,
5116 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5117 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5118 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005119
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005120 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005121}
5122
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005123
5124/*
5125 Public function, see header qcbor/qcbor_decode.h file
5126*/
5127void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005128 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005129 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005130 int64_t *pnMantissa,
5131 int64_t *pnExponent)
5132{
5133 if(pMe->uLastError != QCBOR_SUCCESS) {
5134 return;
5135 }
5136
5137 QCBORItem Item;
5138 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5139
5140 const TagSpecification TagSpec =
5141 {
5142 uTagRequirement,
5143 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5144 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5145 };
5146
5147 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5148}
5149
5150
5151/*
5152 Public function, see header qcbor/qcbor_decode.h file
5153*/
5154void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005155 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005156 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005157 int64_t *pnMantissa,
5158 int64_t *pnExponent)
5159{
5160 if(pMe->uLastError != QCBOR_SUCCESS) {
5161 return;
5162 }
5163
5164 QCBORItem Item;
5165 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5166
5167 const TagSpecification TagSpec =
5168 {
5169 uTagRequirement,
5170 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5171 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5172 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005173
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005174 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5175}
5176
5177
5178/*
5179 Public function, see header qcbor/qcbor_decode.h file
5180*/
5181void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5182 uint8_t uTagRequirement,
5183 UsefulBuf MantissaBuffer,
5184 UsefulBufC *pMantissa,
5185 bool *pbMantissaIsNegative,
5186 int64_t *pnExponent)
5187{
5188 if(pMe->uLastError != QCBOR_SUCCESS) {
5189 return;
5190 }
5191
5192 QCBORItem Item;
5193 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5194 if(uError) {
5195 pMe->uLastError = (uint8_t)uError;
5196 return;
5197 }
5198
5199 const TagSpecification TagSpec =
5200 {
5201 uTagRequirement,
5202 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5203 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5204 };
5205
5206 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
5207}
5208
5209
5210/*
5211 Public function, see header qcbor/qcbor_decode.h file
5212*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005213void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005214 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005215 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005216 UsefulBuf BufferForMantissa,
5217 UsefulBufC *pMantissa,
5218 bool *pbIsNegative,
5219 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005220{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005221 if(pMe->uLastError != QCBOR_SUCCESS) {
5222 return;
5223 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005224
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005225 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005226 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005227 if(pMe->uLastError != QCBOR_SUCCESS) {
5228 return;
5229 }
5230
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005231 const TagSpecification TagSpec =
5232 {
5233 uTagRequirement,
5234 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5235 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5236 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005237
5238 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005239}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005240
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005241
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005242/*
5243 Public function, see header qcbor/qcbor_decode.h file
5244*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005245void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005246 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005247 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005248 UsefulBuf BufferForMantissa,
5249 UsefulBufC *pMantissa,
5250 bool *pbIsNegative,
5251 int64_t *pnExponent)
5252{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005253 if(pMe->uLastError != QCBOR_SUCCESS) {
5254 return;
5255 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005256
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005257 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005258 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5259 if(pMe->uLastError != QCBOR_SUCCESS) {
5260 return;
5261 }
5262
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005263 const TagSpecification TagSpec =
5264 {
5265 uTagRequirement,
5266 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
5267 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5268 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005269
5270 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5271}
5272
5273
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005274/*
5275 Public function, see header qcbor/qcbor_decode.h file
5276*/
5277void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5278 uint8_t uTagRequirement,
5279 int64_t *pnMantissa,
5280 int64_t *pnExponent)
5281{
5282 if(pMe->uLastError != QCBOR_SUCCESS) {
5283 return;
5284 }
5285
5286 QCBORItem Item;
5287 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5288 if(uError) {
5289 pMe->uLastError = (uint8_t)uError;
5290 return;
5291 }
5292 const TagSpecification TagSpec =
5293 {
5294 uTagRequirement,
5295 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5296 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5297 };
5298
5299 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5300}
5301
5302
5303/*
5304 Public function, see header qcbor/qcbor_decode.h file
5305*/
5306void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005307 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005308 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005309 int64_t *pnMantissa,
5310 int64_t *pnExponent)
5311{
5312 if(pMe->uLastError != QCBOR_SUCCESS) {
5313 return;
5314 }
5315
5316 QCBORItem Item;
5317 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5318 if(pMe->uLastError != QCBOR_SUCCESS) {
5319 return;
5320 }
5321
5322 const TagSpecification TagSpec =
5323 {
5324 uTagRequirement,
5325 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5326 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5327 };
5328
5329 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5330}
5331
5332
5333/*
5334 Public function, see header qcbor/qcbor_decode.h file
5335*/
5336void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005337 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005338 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005339 int64_t *pnMantissa,
5340 int64_t *pnExponent)
5341{
5342 if(pMe->uLastError != QCBOR_SUCCESS) {
5343 return;
5344 }
5345
5346 QCBORItem Item;
5347 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5348 if(pMe->uLastError != QCBOR_SUCCESS) {
5349 return;
5350 }
5351
5352 const TagSpecification TagSpec =
5353 {
5354 uTagRequirement,
5355 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5356 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5357 };
5358
5359 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5360}
5361
5362
5363/*
5364 Public function, see header qcbor/qcbor_decode.h file
5365*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005366void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5367 uint8_t uTagRequirement,
5368 UsefulBuf MantissaBuffer,
5369 UsefulBufC *pMantissa,
5370 bool *pbMantissaIsNegative,
5371 int64_t *pnExponent)
5372{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005373 if(pMe->uLastError != QCBOR_SUCCESS) {
5374 return;
5375 }
5376
5377 QCBORItem Item;
5378 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5379 if(uError) {
5380 pMe->uLastError = (uint8_t)uError;
5381 return;
5382 }
5383
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005384 const TagSpecification TagSpec =
5385 {
5386 uTagRequirement,
5387 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5388 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5389 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005390
5391 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005392}
5393
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005394
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005395/*
5396 Public function, see header qcbor/qcbor_decode.h file
5397*/
5398void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005399 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005400 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005401 UsefulBuf BufferForMantissa,
5402 UsefulBufC *pMantissa,
5403 bool *pbIsNegative,
5404 int64_t *pnExponent)
5405{
5406 if(pMe->uLastError != QCBOR_SUCCESS) {
5407 return;
5408 }
5409
5410 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005411 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5412 if(pMe->uLastError != QCBOR_SUCCESS) {
5413 return;
5414 }
5415
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005416 const TagSpecification TagSpec =
5417 {
5418 uTagRequirement,
5419 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5420 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5421 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005422
5423 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5424}
5425
5426
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005427/*
5428 Public function, see header qcbor/qcbor_decode.h file
5429*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005430void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005431 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005432 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005433 UsefulBuf BufferForMantissa,
5434 UsefulBufC *pMantissa,
5435 bool *pbIsNegative,
5436 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005437{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005438 if(pMe->uLastError != QCBOR_SUCCESS) {
5439 return;
5440 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005441
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005442 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005443 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5444 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005445 return;
5446 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005447
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005448 const TagSpecification TagSpec =
5449 {
5450 uTagRequirement,
5451 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
5452 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
5453 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005454
5455 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005456}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005457
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005458#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */