blob: 0c3105c715e6b45640432baf52020474b946d1b3 [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 Lundblade12d32c52018-09-19 11:25:27 -070035#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070036
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070037
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053038/*
39 This casts away the const-ness of a pointer, usually so it can be
40 freed or realloced.
41 */
42#define UNCONST_POINTER(ptr) ((void *)(ptr))
43
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070044
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070045
Laurence Lundblade02625d42020-06-25 14:41:41 -070046inline static bool
47// TODO: add more tests for QCBOR_TYPE_MAP_AS_ARRAY mode in qcbor_decode_tests.c
48QCBORItem_IsMapOrArray(const QCBORItem *pMe)
49{
50 const uint8_t uDataType = pMe->uDataType;
51 return uDataType == QCBOR_TYPE_MAP ||
52 uDataType == QCBOR_TYPE_ARRAY ||
53 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
54}
55
56inline static bool
57QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
58{
59 if(!QCBORItem_IsMapOrArray(pMe)){
60 return false;
61 }
62
63 if(pMe->val.uCount != 0) {
64 return false;
65 }
66 return true;
67}
68
69inline static bool
70QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
71{
72 if(!QCBORItem_IsMapOrArray(pMe)){
73 return false;
74 }
75
76 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
77 return false;
78 }
79 return true;
80}
81
82
Laurence Lundbladeee851742020-01-08 08:37:05 -080083/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070084 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080085 ===========================================================================*/
86
Laurence Lundblade9c905e82020-04-25 11:31:38 -070087/*
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070088 See commecnts about and typedef of QCBORDecodeNesting in qcbor_private.h, the data structure
89 all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -070090
Laurence Lundblade9c905e82020-04-25 11:31:38 -070091
Laurence Lundblade9c905e82020-04-25 11:31:38 -070092
Laurence Lundblade9c905e82020-04-25 11:31:38 -070093 */
94
Laurence Lundblade24d509a2020-06-06 18:43:15 -070095
96inline static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -070097DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -070098{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070099 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700100 /*
101 Limit in DecodeNesting_Descend against more than
102 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
103 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700104 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700105}
106
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700107
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700108inline static uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700109DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700110{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700111 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700112 /*
113 Limit in DecodeNesting_Descend against more than
114 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
115 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700116 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700117}
118
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700119
Laurence Lundblade02625d42020-06-25 14:41:41 -0700120static inline size_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700121DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700122{
123 return pNesting->pCurrentBounded->u.ma.uStartOffset;
124}
125
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700126
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700127inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700128DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700129{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700130 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700131 return true;
132 } else {
133 return false;
134 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700135}
136
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700137
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700138inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700139DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700140{
141 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700142 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700143 return false;
144 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700145 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700146 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700147 return false;
148 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700149 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700150 return true;
151}
152
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700153
Laurence Lundblade642282a2020-06-23 12:00:33 -0700154inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700155DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700156{
157 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700158 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700159 return true;
160 }
161 return false;
162}
163
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700164
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700165inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700166{
167 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
168 return true;
169 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700170 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700171 return true;
172 }
173 return false;
174}
175
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700176
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700177inline static void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700178{
179 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700180 /*
181 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
182 larger than DecodeNesting_EnterBoundedMode which keeps it less than
183 uin32_t so the cast is safe.
184 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700185 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
186}
187
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700188
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700189inline static void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700190{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700191 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700192}
193
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700194
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700195inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700196DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700197{
198 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700199 // No bounded map or array or... set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700200 return false;
201 }
202 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700203 // Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700204 return false;
205 }
206 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700207 // Not at a bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700208 return false;
209 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700210 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700211 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700212 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700213 return false;
214 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700215 // All checks passed, got to the end of a map/array
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700216 return true;
217}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700218
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700219
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700220inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700221DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700222{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700223 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700224 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
225 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700226 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700227 return false;
228 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700229}
230
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700231
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700232inline static bool
233DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700234{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700235 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
236 return true;
237 } else {
238 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700239 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700240}
241
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700242
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700243inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700244DecodeNesting_CheckBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700245{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700246 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700247 return false;
248 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700249
250 if(pNesting->pCurrentBounded->uLevelType != uType) {
251 return false;
252 }
253
254 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700255}
256
Laurence Lundblade02625d42020-06-25 14:41:41 -0700257
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700258inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700259DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700260{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700261 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700262 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700263}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700264
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700265
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700266inline static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700267DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
268{
269 // Only call on a defnite length array / map
270 pNesting->pCurrent->u.ma.uCountCursor++;
271}
272
273
274inline static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700275DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
276{
277 pNesting->pCurrent--;
278}
279
Laurence Lundblade02625d42020-06-25 14:41:41 -0700280
281static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700282DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700283{
284 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700285 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700286 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
287 }
288
289 // The actual descend
290 pNesting->pCurrent++;
291
292 pNesting->pCurrent->uLevelType = uType;
293
294 return QCBOR_SUCCESS;
295}
296
297
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700298inline static QCBORError
299DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700300{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700301 /*
302 Should only be called on map/array.
303
304 Have descended into this before this is called. The job here is
305 just to mark it in bounded mode.
306 */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700307 if(uOffset >= QCBOR_NON_BOUNDED_OFFSET) {
308 return QCBOR_ERR_BUFFER_TOO_LARGE;
309 }
310
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700311 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700312 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700313
314 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700315}
316
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700317
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700318inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700319DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700320 uint8_t uQCBORType,
321 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700322{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700323 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700324
325 if(uCount == 0) {
326 // Nothing to do for empty definite lenth arrays. They are just are
327 // effectively the same as an item that is not a map or array
328 goto Done;
329 // Empty indefinite length maps and arrays are handled elsewhere
330 }
331
332 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700333 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
334 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
335 uError = QCBOR_ERR_ARRAY_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700336 goto Done;
337 }
338
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700339 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700340 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700341 goto Done;
342 }
343
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700344 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700345 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
346 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700347
348 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700349
350Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700351 return uError;;
352}
353
354
355static inline void
356DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
357{
358 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
359}
360
361
362static inline void
363DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
364{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700365 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700366 pNesting->pCurrentBounded--;
367 if(DecodeNesting_IsCurrentBounded(pNesting)) {
368 break;
369 }
370 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700371}
372
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700373static inline void
374DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
375{
376 pNesting->pCurrent = pNesting->pCurrentBounded;
377}
378
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700379
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700380inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700381DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
382 size_t uEndOffset,
383 size_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700384{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700385 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700386
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700387 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700388 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700389 goto Done;
390 }
391
Laurence Lundblade02625d42020-06-25 14:41:41 -0700392 // Fill in the new byte string level
393 // TODO: justify cast
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700394 pNesting->pCurrent->u.bs.uPreviousEndOffset = (uint32_t)uEndOffset;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700395 pNesting->pCurrent->u.bs.uEndOfBstr = (uint32_t)uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700396
Laurence Lundblade02625d42020-06-25 14:41:41 -0700397 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700398 pNesting->pCurrentBounded = pNesting->pCurrent;
399
400Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700401 return uError;;
402}
403
Laurence Lundbladed0304932020-06-27 10:59:38 -0700404
405static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700406DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700407{
408 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700409}
410
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700411
Laurence Lundbladeee851742020-01-08 08:37:05 -0800412inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700413DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700414{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700415 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700416 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
417 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700418}
419
420
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700421inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700422DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700423{
424 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700425 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700426 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700427}
428
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700429
Laurence Lundblade02625d42020-06-25 14:41:41 -0700430static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700431DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700432{
433 *pNesting = *pSave;
434}
435
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700436
Laurence Lundblade02625d42020-06-25 14:41:41 -0700437static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700438DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700439{
440 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
441}
442
443
Laurence Lundblade02625d42020-06-25 14:41:41 -0700444static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700445DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700446{
447 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
448}
449
450
Laurence Lundblade02625d42020-06-25 14:41:41 -0700451#include <stdio.h>
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700452
453const char *TypeStr(uint8_t type)
454{
455 switch(type) {
456 case QCBOR_TYPE_MAP: return " map";
457 case QCBOR_TYPE_ARRAY: return "array";
458 case QCBOR_TYPE_BYTE_STRING: return " bstr";
459 default: return " --- ";
460 }
461}
462
463static char buf[20]; // Not thread safe, but that is OK
464const char *CountString(uint16_t uCount, uint16_t uTotal)
465{
466 if(uTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
467 strcpy(buf, "indefinite");
468 } else {
469 sprintf(buf, "%d/%d", uCount, uTotal);
470 }
471 return buf;
472}
473
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700474
Laurence Lundblade02625d42020-06-25 14:41:41 -0700475void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700476{
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700477#if 0
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700478 printf("---%s--%d/%d--\narrow is current bounded level\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700479 szName,
480 (uint32_t)pBuf->cursor,
481 (uint32_t)pBuf->UB.len);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700482
483 printf("Level Type Count Offsets \n");
Laurence Lundblade02625d42020-06-25 14:41:41 -0700484 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700485 if(&(pNesting->pLevels[i]) > pNesting->pCurrent) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700486 break;
487 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700488
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700489 printf("%2s %2d %s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700490 pNesting->pCurrentBounded == &(pNesting->pLevels[i]) ? "->": " ",
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700491 i,
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700492 TypeStr(pNesting->pLevels[i].uLevelType));
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700493
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700494 if(pNesting->pLevels[i].uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700495 printf(" %5d %5d",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700496 pNesting->pLevels[i].u.bs.uEndOfBstr,
497 pNesting->pLevels[i].u.bs.uPreviousEndOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700498
499 } else {
500 printf("%10.10s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700501 CountString(pNesting->pLevels[i].u.ma.uCountCursor,
502 pNesting->pLevels[i].u.ma.uCountTotal));
503 if(pNesting->pLevels[i].u.ma.uStartOffset != UINT32_MAX) {
504 printf("Bounded start: %u",pNesting->pLevels[i].u.ma.uStartOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700505 }
506 }
507
508 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700509 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700510 printf("\n");
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700511#endif
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700512}
513
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700514
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700515
Laurence Lundbladeee851742020-01-08 08:37:05 -0800516/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800517 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
518
519 The following four functions are pretty wrappers for invocation of
520 the string allocator supplied by the caller.
521
Laurence Lundbladeee851742020-01-08 08:37:05 -0800522 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800523
Laurence Lundbladeee851742020-01-08 08:37:05 -0800524static inline void
525StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800526{
527 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
528}
529
Laurence Lundbladeee851742020-01-08 08:37:05 -0800530// StringAllocator_Reallocate called with pMem NULL is
531// equal to StringAllocator_Allocate()
532static inline UsefulBuf
533StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
534 void *pMem,
535 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800536{
537 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
538}
539
Laurence Lundbladeee851742020-01-08 08:37:05 -0800540static inline UsefulBuf
541StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800542{
543 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
544}
545
Laurence Lundbladeee851742020-01-08 08:37:05 -0800546static inline void
547StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800548{
549 if(pMe->pfAllocator) {
550 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
551 }
552}
553
554
555
Laurence Lundbladeee851742020-01-08 08:37:05 -0800556/*===========================================================================
557 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700558
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800559 See qcbor/qcbor_decode.h for definition of the object
560 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800561 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700562/*
563 Public function, see header file
564 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800565void QCBORDecode_Init(QCBORDecodeContext *me,
566 UsefulBufC EncodedCBOR,
567 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700568{
569 memset(me, 0, sizeof(QCBORDecodeContext));
570 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800571 // Don't bother with error check on decode mode. If a bad value is
572 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700573 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700574 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700575 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700576 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700577 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700578}
579
580
581/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700582 Public function, see header file
583 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800584void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
585 QCBORStringAllocate pfAllocateFunction,
586 void *pAllocateContext,
587 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700588{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800589 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
590 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
591 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700592}
593
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800594
595/*
596 Public function, see header file
597 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700598void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800599 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700600{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700601 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700602 (void)pMe;
603 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700604}
605
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700606
607/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800608 This decodes the fundamental part of a CBOR data item, the type and
609 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800610
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700611 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800612
Laurence Lundbladeee851742020-01-08 08:37:05 -0800613 This does the network->host byte order conversion. The conversion
614 here also results in the conversion for floats in addition to that
615 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800616
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700617 This returns:
618 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800619
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800620 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800621 tags and floats and length for strings and arrays
622
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800623 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800624 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800625
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800626 The int type is preferred to uint8_t for some variables as this
627 avoids integer promotions, can reduce code size and makes
628 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700629 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800630inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
631 int *pnMajorType,
632 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800633 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700634{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700635 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800636
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700637 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800638 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800639
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700640 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800641 const int nTmpMajorType = nInitialByte >> 5;
642 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800643
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800644 // Where the number or argument accumulates
645 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800646
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800647 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700648 // Need to get 1,2,4 or 8 additional argument bytes. Map
649 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800650 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800651
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800652 // Loop getting all the bytes in the argument
653 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800654 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800655 // This shift and add gives the endian conversion
656 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
657 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800658 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800659 // The reserved and thus-far unused additional info values
660 nReturn = QCBOR_ERR_UNSUPPORTED;
661 goto Done;
662 } else {
663 // Less than 24, additional info is argument or 31, an indefinite length
664 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800665 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700666 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800667
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700668 if(UsefulInputBuf_GetError(pUInBuf)) {
669 nReturn = QCBOR_ERR_HIT_END;
670 goto Done;
671 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800672
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700673 // All successful if we got here.
674 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800675 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800676 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800677 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800678
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700679Done:
680 return nReturn;
681}
682
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800683
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700684/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800685 CBOR doesn't explicitly specify two's compliment for integers but all
686 CPUs use it these days and the test vectors in the RFC are so. All
687 integers in the CBOR structure are positive and the major type
688 indicates positive or negative. CBOR can express positive integers
689 up to 2^x - 1 where x is the number of bits and negative integers
690 down to 2^x. Note that negative numbers can be one more away from
691 zero than positive. Stdint, as far as I can tell, uses two's
692 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800693
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700694 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800695 used carefully here, and in particular why it isn't used in the interface.
696 Also see
697 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
698
699 Int is used for values that need less than 16-bits and would be subject
700 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800702inline static QCBORError
703DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700704{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700705 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800706
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700707 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
708 if (uNumber <= INT64_MAX) {
709 pDecodedItem->val.int64 = (int64_t)uNumber;
710 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800711
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700712 } else {
713 pDecodedItem->val.uint64 = uNumber;
714 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800715
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700716 }
717 } else {
718 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800719 // CBOR's representation of negative numbers lines up with the
720 // two-compliment representation. A negative integer has one
721 // more in range than a positive integer. INT64_MIN is
722 // equal to (-INT64_MAX) - 1.
723 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800725
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700726 } else {
727 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000728 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700729 nReturn = QCBOR_ERR_INT_OVERFLOW;
730 }
731 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800732
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700733 return nReturn;
734}
735
736// Make sure #define value line up as DecodeSimple counts on this.
737#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
738#error QCBOR_TYPE_FALSE macro value wrong
739#endif
740
741#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
742#error QCBOR_TYPE_TRUE macro value wrong
743#endif
744
745#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
746#error QCBOR_TYPE_NULL macro value wrong
747#endif
748
749#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
750#error QCBOR_TYPE_UNDEF macro value wrong
751#endif
752
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700753#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
754#error QCBOR_TYPE_BREAK macro value wrong
755#endif
756
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700757#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
758#error QCBOR_TYPE_DOUBLE macro value wrong
759#endif
760
761#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
762#error QCBOR_TYPE_FLOAT macro value wrong
763#endif
764
765/*
766 Decode true, false, floats, break...
767 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800768inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800769DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700770{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700771 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800772
Laurence Lundbladeee851742020-01-08 08:37:05 -0800773 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800774 // above make sure uAdditionalInfo values line up with uDataType values.
775 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
776 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800777
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800778 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800779 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
780 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800781
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700782 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700783 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
784 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700785 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700786 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700787 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
788 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700789 break;
790 case DOUBLE_PREC_FLOAT:
791 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700792 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700793 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800794
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700795 case CBOR_SIMPLEV_FALSE: // 20
796 case CBOR_SIMPLEV_TRUE: // 21
797 case CBOR_SIMPLEV_NULL: // 22
798 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700799 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700800 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800801
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700802 case CBOR_SIMPLEV_ONEBYTE: // 24
803 if(uNumber <= CBOR_SIMPLE_BREAK) {
804 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700805 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700806 goto Done;
807 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800808 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700809 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800810
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700811 default: // 0-19
812 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800813 /*
814 DecodeTypeAndNumber will make uNumber equal to
815 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
816 safe because the 2, 4 and 8 byte lengths of uNumber are in
817 the double/float cases above
818 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700819 pDecodedItem->val.uSimple = (uint8_t)uNumber;
820 break;
821 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800822
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700823Done:
824 return nReturn;
825}
826
827
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700828/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530829 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700830 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800831inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
832 int nMajorType,
833 uint64_t uStrLen,
834 UsefulInputBuf *pUInBuf,
835 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700836{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700837 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800838
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800839 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
840 // This check makes the casts to size_t below safe.
841
842 // 4 bytes less than the largest sizeof() so this can be tested by
843 // putting a SIZE_MAX length in the CBOR test input (no one will
844 // care the limit on strings is 4 bytes shorter).
845 if(uStrLen > SIZE_MAX-4) {
846 nReturn = QCBOR_ERR_STRING_TOO_LONG;
847 goto Done;
848 }
849
850 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530851 if(UsefulBuf_IsNULLC(Bytes)) {
852 // Failed to get the bytes for this string item
853 nReturn = QCBOR_ERR_HIT_END;
854 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700855 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530856
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800857 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530858 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800859 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530860 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700861 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530862 goto Done;
863 }
864 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800865 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530866 } else {
867 // Normal case with no string allocator
868 pDecodedItem->val.string = Bytes;
869 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800870 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800871 // Cast because ternary operator causes promotion to integer
872 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
873 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800874
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530875Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700876 return nReturn;
877}
878
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700879
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800880
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700881
882
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700883
884
Laurence Lundbladeee851742020-01-08 08:37:05 -0800885// Make sure the constants align as this is assumed by
886// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700887#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
888#error QCBOR_TYPE_ARRAY value not lined up with major type
889#endif
890#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
891#error QCBOR_TYPE_MAP value not lined up with major type
892#endif
893
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700894/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800895 This gets a single data item and decodes it including preceding
896 optional tagging. This does not deal with arrays and maps and nesting
897 except to decode the data item introducing them. Arrays and maps are
898 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800899
Laurence Lundbladeee851742020-01-08 08:37:05 -0800900 Errors detected here include: an array that is too long to decode,
901 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700902 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800903static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
904 QCBORItem *pDecodedItem,
905 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700906{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700907 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800908
Laurence Lundbladeee851742020-01-08 08:37:05 -0800909 /*
910 Get the major type and the number. Number could be length of more
911 bytes or the value depending on the major type nAdditionalInfo is
912 an encoding of the length of the uNumber and is needed to decode
913 floats and doubles
914 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800915 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700916 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800917 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800918
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700919 memset(pDecodedItem, 0, sizeof(QCBORItem));
920
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800921 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800922
Laurence Lundbladeee851742020-01-08 08:37:05 -0800923 // Error out here if we got into trouble on the type and number. The
924 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700925 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700926 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700927 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800928
Laurence Lundbladeee851742020-01-08 08:37:05 -0800929 // At this point the major type and the value are valid. We've got
930 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800931 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700932 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
933 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800934 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700935 nReturn = QCBOR_ERR_BAD_INT;
936 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800937 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700938 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700939 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800940
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700941 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
942 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800943 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
944 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
945 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
946 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530947 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700948 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800949 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700950 }
951 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800952
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700953 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
954 case CBOR_MAJOR_TYPE_MAP: // Major type 5
955 // Record the number of items in the array or map
956 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
957 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
958 goto Done;
959 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800960 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700961 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700962 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800963 // type conversion OK because of check above
964 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700965 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800966 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800967 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
968 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700969 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800970
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700971 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800972 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700973 nReturn = QCBOR_ERR_BAD_INT;
974 } else {
975 pDecodedItem->val.uTagV = uNumber;
976 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
977 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700978 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800979
Laurence Lundbladeee851742020-01-08 08:37:05 -0800980 case CBOR_MAJOR_TYPE_SIMPLE:
981 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800982 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700983 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800984
Laurence Lundbladeee851742020-01-08 08:37:05 -0800985 default:
986 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700987 nReturn = QCBOR_ERR_UNSUPPORTED;
988 break;
989 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800990
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700991Done:
992 return nReturn;
993}
994
995
996
997/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800998 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800999 individual chunk items together into one QCBORItem using the string
1000 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001001
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301002 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001003 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001004static inline QCBORError
1005GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001006{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001007 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001008
1009 // Get pointer to string allocator. First use is to pass it to
1010 // GetNext_Item() when option is set to allocate for *every* string.
1011 // Second use here is to allocate space to coallese indefinite
1012 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001013 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1014 &(me->StringAllocator) :
1015 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001016
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001017 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001018 nReturn = GetNext_Item(&(me->InBuf),
1019 pDecodedItem,
1020 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001021 if(nReturn) {
1022 goto Done;
1023 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001024
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001025 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301026 // code in this function from here down can be eliminated. Run tests, except
1027 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001028
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001029 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001030 const uint8_t uStringType = pDecodedItem->uDataType;
1031 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001032 goto Done; // no need to do any work here on non-string types
1033 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001034
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001035 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301036 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001037 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001038 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001039
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301040 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001041 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001042 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1043 goto Done;
1044 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001045
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001046 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001047 UsefulBufC FullString = NULLUsefulBufC;
1048
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001049 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001050 // Get item for next chunk
1051 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001052 // NULL string allocator passed here. Do not need to allocate
1053 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001054 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001055 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001056 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001057 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001058
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301059 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001060 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001061 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001062 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301063 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001064 break;
1065 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001066
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001067 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301068 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001069 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001070 if(StringChunkItem.uDataType != uStringType ||
1071 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001072 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001073 break;
1074 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001075
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301076 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001077 // The first time throurgh FullString.ptr is NULL and this is
1078 // equivalent to StringAllocator_Allocate()
1079 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1080 UNCONST_POINTER(FullString.ptr),
1081 FullString.len + StringChunkItem.val.string.len);
1082
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001083 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301084 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001085 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001086 break;
1087 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001088
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001089 // Copy new string chunk at the end of string so far.
1090 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001091 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001092
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001093 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1094 // Getting the item failed, clean up the allocated memory
1095 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001096 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001097
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001098Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001099 return nReturn;
1100}
1101
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001102
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001103static uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1104 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001105 return uTagVal;
1106 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001107 int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001108 return me->auMappedTags[x];
1109 }
1110}
1111
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001112/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001113 Gets all optional tag data items preceding a data item that is not an
1114 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001115 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001116static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001117GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001118{
Laurence Lundblade30816f22018-11-10 13:40:22 +07001119 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001120
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001121 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1122 CBOR_TAG_INVALID16,
1123 CBOR_TAG_INVALID16,
1124 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001125
Laurence Lundblade59289e52019-12-30 13:44:37 -08001126 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001127 for(;;) {
1128 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001129 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001130 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001131 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001132
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001133 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1134 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001135 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001136 break;
1137 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001138
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001139 // Is there room for the tag in the tags list?
1140 size_t uTagIndex;
1141 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001142 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001143 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001144 }
1145 }
1146 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001147 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001148 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001149
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001150 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001151 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001152 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001153 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001154 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001155 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001156 break;
1157 }
1158 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001159 // TODO: test this
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001160 break;
1161 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001162 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001163 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1164 // No room for the tag
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001165 // Should never happen as long as QCBOR_MAX_TAGS_PER_ITEM <= QCBOR_NUM_MAPPED_TAGS
1166 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001167 }
1168
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001169 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001170 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001171 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001172
1173 } else {
1174 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001175 }
1176 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001177
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001178Done:
1179 return nReturn;
1180}
1181
1182
1183/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001184 This layer takes care of map entries. It combines the label and data
1185 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001186 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001187static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001188GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001189{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001190 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001191 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001192 if(nReturn)
1193 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001194
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001195 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001196 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001197 goto Done;
1198 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001199
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001200 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1201 // In a map and caller wants maps decoded, not treated as arrays
1202
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001203 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001204 // If in a map and the right decoding mode, get the label
1205
Laurence Lundbladeee851742020-01-08 08:37:05 -08001206 // Save label in pDecodedItem and get the next which will
1207 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001208 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001209 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001210 if(nReturn)
1211 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001212
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301213 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001214
1215 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1216 // strings are always good labels
1217 pDecodedItem->label.string = LabelItem.val.string;
1218 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1219 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001220 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001221 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1222 goto Done;
1223 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1224 pDecodedItem->label.int64 = LabelItem.val.int64;
1225 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1226 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1227 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1228 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1229 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1230 pDecodedItem->label.string = LabelItem.val.string;
1231 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1232 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1233 } else {
1234 // label is not an int or a string. It is an arrray
1235 // or a float or such and this implementation doesn't handle that.
1236 // Also, tags on labels are ignored.
1237 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1238 goto Done;
1239 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001240 }
1241 } else {
1242 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001243 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1244 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1245 goto Done;
1246 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001247 // Decoding a map as an array
1248 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001249 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1250 // Cast is needed because of integer promotion
1251 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001252 }
1253 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001254
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001255Done:
1256 return nReturn;
1257}
1258
1259
Laurence Lundblade02625d42020-06-25 14:41:41 -07001260/*
1261 See if next item is a CBOR break. If it is, it is consumed,
1262 if not it is not consumed.
1263*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001264static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001265NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1266{
1267 *pbNextIsBreak = false;
1268 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001269 QCBORItem Peek;
1270 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1271 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1272 if(uReturn != QCBOR_SUCCESS) {
1273 return uReturn;
1274 }
1275 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001276 // It is not a break, rewind so it can be processed normally.
1277 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001278 } else {
1279 *pbNextIsBreak = true;
1280 }
1281 }
1282
1283 return QCBOR_SUCCESS;
1284}
1285
1286
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001287/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001288 An item was just consumed, now figure out if it was the
1289 end of an array or map that can be closed out. That
1290 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001291*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001292static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001293{
1294 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001295
Laurence Lundblade642282a2020-06-23 12:00:33 -07001296 /* This loops ascending nesting levels as long as there is ascending to do */
1297 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1298
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001299 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001300 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001301 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1302 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001303 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001304 break;
1305 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001306 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001307
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001308 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001309 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001310 bool bIsBreak = false;
1311 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1312 if(uReturn != QCBOR_SUCCESS) {
1313 goto Done;
1314 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001315
1316 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001317 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001318 break;
1319 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001320
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001321 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001322 /*
1323 Break occurred inside a bstr-wrapped CBOR or
1324 in the top level sequence. This is always an
1325 error because neither are an indefinte length
1326 map/array.
1327 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001328 uReturn = QCBOR_ERR_BAD_BREAK;
1329 goto Done;
1330 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001331 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001332 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001333
Laurence Lundblade02625d42020-06-25 14:41:41 -07001334 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001335
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001336 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001337 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001338 /* 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 -07001339 if(bMarkEnd) {
1340 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001341 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001342
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001343 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001344 break;
1345 }
1346
1347 /* Finally, actually ascend one level. */
1348 DecodeNesting_Ascend(&(pMe->nesting));
1349 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001350
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001351 uReturn = QCBOR_SUCCESS;
1352
1353Done:
1354 return uReturn;
1355}
1356
1357
1358/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001359 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001360 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1361 indefinte length maps and arrays by looking at the item count or
1362 finding CBOR breaks. It detects the ends of the top-level sequence
1363 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001364 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001365static QCBORError
1366QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001367{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001368 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001369 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001370
Laurence Lundblade642282a2020-06-23 12:00:33 -07001371 /*
1372 If out of bytes to consume, it is either the end of the top-level
1373 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001374
Laurence Lundblade642282a2020-06-23 12:00:33 -07001375 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1376 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1377 CBOR is exited, the length is set back to the top-level's length
1378 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001379 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001380 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001381 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001382 goto Done;
1383 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001384
Laurence Lundblade642282a2020-06-23 12:00:33 -07001385 /*
1386 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001387 array. The check for the end of an indefinite length array is
1388 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001389 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001390 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001391 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001392 goto Done;
1393 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001394
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001395 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001396 uReturn = GetNext_MapEntry(me, pDecodedItem);
1397 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001398 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001399 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301400
Laurence Lundblade642282a2020-06-23 12:00:33 -07001401 /*
1402 Breaks ending arrays/maps are always processed at the end of this
1403 function. They should never show up here.
1404 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301405 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001406 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301407 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301408 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001409
Laurence Lundblade642282a2020-06-23 12:00:33 -07001410 /*
1411 Record the nesting level for this data item before processing any
1412 of decrementing and descending.
1413 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001414 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001415
Laurence Lundblade642282a2020-06-23 12:00:33 -07001416
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001417 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001418 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001419 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001420 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001421
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001422 Empty indefinite length maps and arrays are descended into, but then ascended out
Laurence Lundblade02625d42020-06-25 14:41:41 -07001423 of in the next chunk of code.
1424
1425 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001426 encloses them so a decrement needs to be done for them too, but
1427 that is done only when all the items in them have been
1428 processed, not when they are opened with the exception of an
1429 empty map or array.
1430 */
1431 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1432 pDecodedItem->uDataType,
1433 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001434 if(uReturn != QCBOR_SUCCESS) {
1435 goto Done;
1436 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001437 }
1438
Laurence Lundblade02625d42020-06-25 14:41:41 -07001439 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1440 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1441 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001442 /*
1443 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001444 - A non-aggregate like an integer or string
1445 - An empty definite length map or array
1446 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001447
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001448 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001449 definite length map/array and break detection for an indefinite
1450 length map/array. If the end of the map/array was reached, then
1451 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001452 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001453 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001454 if(uReturn) {
1455 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001456 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301457 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001458
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001459 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001460 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001461 Tell the caller what level is next. This tells them what
1462 maps/arrays were closed out and makes it possible for them to
1463 reconstruct the tree with just the information returned in
1464 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001465 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001466 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001467 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001468 pDecodedItem->uNextNestLevel = 0;
1469 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001470 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001471 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001472
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001473Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001474 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001475 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001476 memset(pDecodedItem, 0, sizeof(QCBORItem));
1477 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001478 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001479}
1480
1481
Laurence Lundblade59289e52019-12-30 13:44:37 -08001482/*
1483 Mostly just assign the right data type for the date string.
1484 */
1485inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1486{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001487 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1488 return QCBOR_ERR_BAD_OPT_TAG;
1489 }
1490
1491 const UsefulBufC Temp = pDecodedItem->val.string;
1492 pDecodedItem->val.dateString = Temp;
1493 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1494 return QCBOR_SUCCESS;
1495}
1496
1497
1498/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001499 The epoch formatted date. Turns lots of different forms of encoding
1500 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001501 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001502static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001503{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001504 QCBORError nReturn = QCBOR_SUCCESS;
1505
1506 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1507
1508 switch (pDecodedItem->uDataType) {
1509
1510 case QCBOR_TYPE_INT64:
1511 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1512 break;
1513
1514 case QCBOR_TYPE_UINT64:
1515 if(pDecodedItem->val.uint64 > INT64_MAX) {
1516 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1517 goto Done;
1518 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001519 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001520 break;
1521
1522 case QCBOR_TYPE_DOUBLE:
1523 {
1524 // This comparison needs to be done as a float before
1525 // conversion to an int64_t to be able to detect doubles
1526 // that are too large to fit into an int64_t. A double
1527 // has 52 bits of preceision. An int64_t has 63. Casting
1528 // INT64_MAX to a double actually causes a round up which
1529 // is bad and wrong for the comparison because it will
1530 // allow conversion of doubles that can't fit into a
1531 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1532 // the cutoff point as if that rounds up in conversion to
1533 // double it will still be less than INT64_MAX. 0x7ff is
1534 // picked because it has 11 bits set.
1535 //
1536 // INT64_MAX seconds is on the order of 10 billion years,
1537 // and the earth is less than 5 billion years old, so for
1538 // most uses this conversion error won't occur even though
1539 // doubles can go much larger.
1540 //
1541 // Without the 0x7ff there is a ~30 minute range of time
1542 // values 10 billion years in the past and in the future
1543 // where this this code would go wrong.
1544 const double d = pDecodedItem->val.dfnum;
1545 if(d > (double)(INT64_MAX - 0x7ff)) {
1546 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1547 goto Done;
1548 }
1549 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1550 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1551 }
1552 break;
1553
1554 default:
1555 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1556 goto Done;
1557 }
1558 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1559
1560Done:
1561 return nReturn;
1562}
1563
1564
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001565/*
1566 Mostly just assign the right data type for the bignum.
1567 */
1568inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1569{
1570 // Stack Use: UsefulBuf 1 -- 16
1571 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1572 return QCBOR_ERR_BAD_OPT_TAG;
1573 }
1574 const UsefulBufC Temp = pDecodedItem->val.string;
1575 pDecodedItem->val.bigNum = Temp;
1576 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1577 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1578 : QCBOR_TYPE_NEGBIGNUM);
1579 return QCBOR_SUCCESS;
1580}
1581
1582
Laurence Lundblade59289e52019-12-30 13:44:37 -08001583#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1584/*
1585 Decode decimal fractions and big floats.
1586
1587 When called pDecodedItem must be the array that is tagged as a big
1588 float or decimal fraction, the array that has the two members, the
1589 exponent and mantissa.
1590
1591 This will fetch and decode the exponent and mantissa and put the
1592 result back into pDecodedItem.
1593 */
1594inline static QCBORError
1595QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1596{
1597 QCBORError nReturn;
1598
1599 // --- Make sure it is an array; track nesting level of members ---
1600 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1601 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1602 goto Done;
1603 }
1604
1605 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001606 // definite length arrays, but not for indefnite. Instead remember
1607 // the nesting level the two integers must be at, which is one
1608 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001609 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1610
1611 // --- Is it a decimal fraction or a bigfloat? ---
1612 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1613 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1614
1615 // --- Get the exponent ---
1616 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001617 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001618 if(nReturn != QCBOR_SUCCESS) {
1619 goto Done;
1620 }
1621 if(exponentItem.uNestingLevel != nNestLevel) {
1622 // Array is empty or a map/array encountered when expecting an int
1623 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1624 goto Done;
1625 }
1626 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1627 // Data arriving as an unsigned int < INT64_MAX has been converted
1628 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1629 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1630 // will be too large for this to handle and thus an error that will
1631 // get handled in the next else.
1632 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1633 } else {
1634 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1635 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1636 goto Done;
1637 }
1638
1639 // --- Get the mantissa ---
1640 QCBORItem mantissaItem;
1641 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1642 if(nReturn != QCBOR_SUCCESS) {
1643 goto Done;
1644 }
1645 if(mantissaItem.uNestingLevel != nNestLevel) {
1646 // Mantissa missing or map/array encountered when expecting number
1647 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1648 goto Done;
1649 }
1650 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1651 // Data arriving as an unsigned int < INT64_MAX has been converted
1652 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1653 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1654 // will be too large for this to handle and thus an error that
1655 // will get handled in an else below.
1656 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1657 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1658 // Got a good big num mantissa
1659 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1660 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001661 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1662 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1663 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001664 } else {
1665 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1666 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1667 goto Done;
1668 }
1669
1670 // --- Check that array only has the two numbers ---
1671 if(mantissaItem.uNextNestLevel == nNestLevel) {
1672 // Extra items in the decimal fraction / big num
1673 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1674 goto Done;
1675 }
1676
1677Done:
1678
1679 return nReturn;
1680}
1681#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1682
1683
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001684
1685/*
1686 */
1687inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1688{
1689 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1690 return QCBOR_ERR_BAD_OPT_TAG;
1691 }
1692 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1693 return QCBOR_SUCCESS;
1694}
1695
1696
1697inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1698{
1699 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1700 return QCBOR_ERR_BAD_OPT_TAG;
1701 }
1702 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1703 return QCBOR_SUCCESS;
1704}
1705
1706
1707inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1708{
1709 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1710 return QCBOR_ERR_BAD_OPT_TAG;
1711 }
1712 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1713 return QCBOR_SUCCESS;
1714}
1715
1716
1717inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1718{
1719 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1720 return QCBOR_ERR_BAD_OPT_TAG;
1721 }
1722 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1723 return QCBOR_SUCCESS;
1724}
1725
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001726inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1727{
1728 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1729 return QCBOR_ERR_BAD_OPT_TAG;
1730 }
1731 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1732 return QCBOR_SUCCESS;
1733}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001734
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001735
1736inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1737{
1738 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1739 return QCBOR_ERR_BAD_OPT_TAG;
1740 }
1741 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
1742 return QCBOR_SUCCESS;
1743}
1744
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001745inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1746{
1747 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1748 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
1749 } else if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1750 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1751 } else {
1752 return QCBOR_ERR_BAD_OPT_TAG;
1753 }
1754 return QCBOR_SUCCESS;
1755}
1756
1757
1758/*
1759 */
1760inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1761{
1762 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1763 return QCBOR_ERR_BAD_OPT_TAG;
1764 }
1765 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1766 return QCBOR_SUCCESS;
1767}
1768
1769
Laurence Lundblade59289e52019-12-30 13:44:37 -08001770/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001771 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001772 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001773QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001774QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001775{
1776 QCBORError nReturn;
1777
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001778 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001779 if(nReturn != QCBOR_SUCCESS) {
1780 goto Done;
1781 }
1782
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001783 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1784 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001785
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001786 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001787 nReturn = DecodeDateString(pDecodedItem);
1788 break;
1789
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001790 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001791 nReturn = DecodeDateEpoch(pDecodedItem);
1792 break;
1793
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001794 case CBOR_TAG_POS_BIGNUM:
1795 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001796 nReturn = DecodeBigNum(pDecodedItem);
1797 break;
1798
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001799 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1800 case CBOR_TAG_DECIMAL_FRACTION:
1801 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001802 // For aggregate tagged types, what goes into pTags is only collected
1803 // from the surrounding data item, not the contents, so pTags is not
1804 // passed on here.
1805
1806 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1807 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001808 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001809
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001810 case CBOR_TAG_CBOR:
1811 nReturn = DecodeWrappedCBOR(pDecodedItem);
1812 break;
1813
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001814 case CBOR_TAG_CBOR_SEQUENCE:
1815 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1816 break;
1817
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001818 case CBOR_TAG_URI:
1819 nReturn = DecodeURI(pDecodedItem);
1820 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001821
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001822 case CBOR_TAG_B64URL:
1823 nReturn = DecodeB64URL(pDecodedItem);
1824 break;
1825
1826 case CBOR_TAG_B64:
1827 nReturn = DecodeB64(pDecodedItem);
1828 break;
1829
1830 case CBOR_TAG_MIME:
1831 case CBOR_TAG_BINARY_MIME:
1832 nReturn = DecodeMIME(pDecodedItem);
1833 break;
1834
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001835 case CBOR_TAG_REGEX:
1836 nReturn = DecodeRegex(pDecodedItem);
1837 break;
1838
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001839 case CBOR_TAG_BIN_UUID:
1840 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001841 break;
1842
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001843 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001844 // The end of the tag list or no tags
1845 // Successful exit from the loop.
1846 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001847
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001848 default:
1849 // A tag that is not understood
1850 // A successful exit from the loop
1851 goto Done;
1852
1853 }
1854 if(nReturn != QCBOR_SUCCESS) {
1855 goto Done;
1856 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001857 }
1858
1859Done:
1860 if(nReturn != QCBOR_SUCCESS) {
1861 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1862 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1863 }
1864 return nReturn;
1865}
1866
1867
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001868QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1869{
1870 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1871
1872 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1873
1874 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1875
1876 return uErr;
1877}
1878
1879
Laurence Lundblade59289e52019-12-30 13:44:37 -08001880/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001881 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001882 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001883QCBORError
1884QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1885 QCBORItem *pDecodedItem,
1886 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001887{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001888 QCBORError nReturn;
1889
1890 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1891 if(nReturn != QCBOR_SUCCESS) {
1892 return nReturn;
1893 }
1894
1895 if(pTags != NULL) {
1896 pTags->uNumUsed = 0;
1897 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001898 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001899 break;
1900 }
1901 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1902 return QCBOR_ERR_TOO_MANY_TAGS;
1903 }
1904 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1905 pTags->uNumUsed++;
1906 }
1907 }
1908
1909 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001910}
1911
1912
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001913/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301914 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301915 next one down. If a layer has no work to do for a particular item
1916 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001917
Laurence Lundblade59289e52019-12-30 13:44:37 -08001918 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1919 tagged data items, turning them into the local C representation.
1920 For the most simple it is just associating a QCBOR_TYPE with the data. For
1921 the complex ones that an aggregate of data items, there is some further
1922 decoding and a little bit of recursion.
1923
1924 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301925 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301926 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001927 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001928
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301929 - GetNext_MapEntry -- This handles the combining of two
1930 items, the label and the data, that make up a map entry.
1931 It only does work on maps. It combines the label and data
1932 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001933
Laurence Lundblade59289e52019-12-30 13:44:37 -08001934 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1935 tags into bit flags associated with the data item. No actual decoding
1936 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001937
Laurence Lundblade59289e52019-12-30 13:44:37 -08001938 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301939 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301940 string allocater to create contiguous space for the item. It
1941 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001942
Laurence Lundblade59289e52019-12-30 13:44:37 -08001943 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1944 atomic data item has a "major type", an integer "argument" and optionally
1945 some content. For text and byte strings, the content is the bytes
1946 that make up the string. These are the smallest data items that are
1947 considered to be well-formed. The content may also be other data items in
1948 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001949
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001950 Roughly this takes 300 bytes of stack for vars. Need to
1951 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001952
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301953 */
1954
1955
1956/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001957 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001958 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001959int QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001960 const QCBORItem *pItem,
1961 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001962{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001963 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001964 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001965 break;
1966 }
1967 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1968 return 1;
1969 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001970 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001971
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001972 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001973}
1974
1975
1976/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001977 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001978 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001979QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001980{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001981 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001982
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001983 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001984 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001985 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1986 goto Done;
1987 }
1988
1989 // Error out if not all the bytes are consumed
1990 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1991 nReturn = QCBOR_ERR_EXTRA_BYTES;
1992 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001993
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001994Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301995 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001996 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001997 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001998
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001999 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002000}
2001
2002
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002003/*
2004Public function, see header qcbor/qcbor_decode.h file
2005*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002006uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2007 const QCBORItem *pItem,
2008 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002009{
2010 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
2011 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002012 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002013 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002014 }
2015}
2016
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002017
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002018/*
2019
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002020Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002021
Laurence Lundbladeee851742020-01-08 08:37:05 -08002022 - Hit end of input before it was expected while decoding type and
2023 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002024
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002025 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002026
Laurence Lundbladeee851742020-01-08 08:37:05 -08002027 - Hit end of input while decoding a text or byte string
2028 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002029
Laurence Lundbladeee851742020-01-08 08:37:05 -08002030 - Encountered conflicting tags -- e.g., an item is tagged both a date
2031 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002032
Laurence Lundbladeee851742020-01-08 08:37:05 -08002033 - Encontered an array or mapp that has too many items
2034 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002035
Laurence Lundbladeee851742020-01-08 08:37:05 -08002036 - Encountered array/map nesting that is too deep
2037 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002038
Laurence Lundbladeee851742020-01-08 08:37:05 -08002039 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2040 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002041
Laurence Lundbladeee851742020-01-08 08:37:05 -08002042 - The type of a map label is not a string or int
2043 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002044
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002045 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002046
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002047 */
2048
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002049
2050
Laurence Lundbladef6531662018-12-04 10:42:22 +09002051
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002052/* ===========================================================================
2053 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002054
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002055 This implements a simple sting allocator for indefinite length
2056 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2057 implements the function type QCBORStringAllocate and allows easy
2058 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002059
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002060 This particular allocator is built-in for convenience. The caller
2061 can implement their own. All of this following code will get
2062 dead-stripped if QCBORDecode_SetMemPool() is not called.
2063
2064 This is a very primitive memory allocator. It does not track
2065 individual allocations, only a high-water mark. A free or
2066 reallocation must be of the last chunk allocated.
2067
2068 The size of the pool and offset to free memory are packed into the
2069 first 8 bytes of the memory pool so we don't have to keep them in
2070 the decode context. Since the address of the pool may not be
2071 aligned, they have to be packed and unpacked as if they were
2072 serialized data of the wire or such.
2073
2074 The sizes packed in are uint32_t to be the same on all CPU types
2075 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002076 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002077
2078
Laurence Lundbladeee851742020-01-08 08:37:05 -08002079static inline int
2080MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002081{
2082 // Use of UsefulInputBuf is overkill, but it is convenient.
2083 UsefulInputBuf UIB;
2084
Laurence Lundbladeee851742020-01-08 08:37:05 -08002085 // Just assume the size here. It was checked during SetUp so
2086 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002087 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2088 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2089 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2090 return UsefulInputBuf_GetError(&UIB);
2091}
2092
2093
Laurence Lundbladeee851742020-01-08 08:37:05 -08002094static inline int
2095MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002096{
2097 // Use of UsefulOutBuf is overkill, but convenient. The
2098 // length check performed here is useful.
2099 UsefulOutBuf UOB;
2100
2101 UsefulOutBuf_Init(&UOB, Pool);
2102 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2103 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2104 return UsefulOutBuf_GetError(&UOB);
2105}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002106
2107
2108/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002109 Internal function for an allocation, reallocation free and destuct.
2110
2111 Having only one function rather than one each per mode saves space in
2112 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002113
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002114 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2115 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002116static UsefulBuf
2117MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002118{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002119 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002120
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002121 uint32_t uPoolSize;
2122 uint32_t uFreeOffset;
2123
2124 if(uNewSize > UINT32_MAX) {
2125 // This allocator is only good up to 4GB. This check should
2126 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2127 goto Done;
2128 }
2129 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2130
2131 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2132 goto Done;
2133 }
2134
2135 if(uNewSize) {
2136 if(pMem) {
2137 // REALLOCATION MODE
2138 // Calculate pointer to the end of the memory pool. It is
2139 // assumed that pPool + uPoolSize won't wrap around by
2140 // assuming the caller won't pass a pool buffer in that is
2141 // not in legitimate memory space.
2142 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2143
2144 // Check that the pointer for reallocation is in the range of the
2145 // pool. This also makes sure that pointer math further down
2146 // doesn't wrap under or over.
2147 if(pMem >= pPool && pMem < pPoolEnd) {
2148 // Offset to start of chunk for reallocation. This won't
2149 // wrap under because of check that pMem >= pPool. Cast
2150 // is safe because the pool is always less than UINT32_MAX
2151 // because of check in QCBORDecode_SetMemPool().
2152 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2153
2154 // Check to see if the allocation will fit. uPoolSize -
2155 // uMemOffset will not wrap under because of check that
2156 // pMem is in the range of the uPoolSize by check above.
2157 if(uNewSize <= uPoolSize - uMemOffset) {
2158 ReturnValue.ptr = pMem;
2159 ReturnValue.len = uNewSize;
2160
2161 // Addition won't wrap around over because uNewSize was
2162 // checked to be sure it is less than the pool size.
2163 uFreeOffset = uMemOffset + uNewSize32;
2164 }
2165 }
2166 } else {
2167 // ALLOCATION MODE
2168 // uPoolSize - uFreeOffset will not underflow because this
2169 // pool implementation makes sure uFreeOffset is always
2170 // smaller than uPoolSize through this check here and
2171 // reallocation case.
2172 if(uNewSize <= uPoolSize - uFreeOffset) {
2173 ReturnValue.len = uNewSize;
2174 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002175 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002176 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002177 }
2178 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002179 if(pMem) {
2180 // FREE MODE
2181 // Cast is safe because of limit on pool size in
2182 // QCBORDecode_SetMemPool()
2183 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2184 } else {
2185 // DESTRUCT MODE
2186 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002187 }
2188 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002189
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002190 UsefulBuf Pool = {pPool, uPoolSize};
2191 MemPool_Pack(Pool, uFreeOffset);
2192
2193Done:
2194 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002195}
2196
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002197
Laurence Lundbladef6531662018-12-04 10:42:22 +09002198/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002199 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002200 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002201QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2202 UsefulBuf Pool,
2203 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002204{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002205 // The pool size and free mem offset are packed into the beginning
2206 // of the pool memory. This compile time check make sure the
2207 // constant in the header is correct. This check should optimize
2208 // down to nothing.
2209 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002210 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002211 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002212
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002213 // The pool size and free offset packed in to the beginning of pool
2214 // memory are only 32-bits. This check will optimize out on 32-bit
2215 // machines.
2216 if(Pool.len > UINT32_MAX) {
2217 return QCBOR_ERR_BUFFER_TOO_LARGE;
2218 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002219
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002220 // This checks that the pool buffer given is big enough.
2221 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2222 return QCBOR_ERR_BUFFER_TOO_SMALL;
2223 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002224
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002225 pMe->StringAllocator.pfAllocator = MemPool_Function;
2226 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2227 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002228
Laurence Lundblade30816f22018-11-10 13:40:22 +07002229 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002230}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002231
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002232
2233
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002234
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002235
2236
2237/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002238 Consume an entire map or array (and do next to
2239 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002240 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002241static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002242ConsumeItem(QCBORDecodeContext *pMe,
2243 const QCBORItem *pItemToConsume,
2244 uint_fast8_t *puNextNestLevel)
2245{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002246 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002247 QCBORItem Item;
2248
Laurence Lundblade02625d42020-06-25 14:41:41 -07002249 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002250
Laurence Lundblade02625d42020-06-25 14:41:41 -07002251 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002252 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002253
Laurence Lundblade1341c592020-04-11 14:19:05 -07002254 /* This works for definite and indefinite length
2255 * maps and arrays by using the nesting level
2256 */
2257 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002258 uReturn = QCBORDecode_GetNext(pMe, &Item);
2259 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002260 goto Done;
2261 }
2262 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002263
Laurence Lundblade1341c592020-04-11 14:19:05 -07002264 if(puNextNestLevel != NULL) {
2265 *puNextNestLevel = Item.uNextNestLevel;
2266 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002267 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002268
Laurence Lundblade1341c592020-04-11 14:19:05 -07002269 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002270 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002271 if(puNextNestLevel != NULL) {
2272 /* Just pass the nesting level through */
2273 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2274 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002275 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002276 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002277
2278Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002279 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002280}
2281
2282
Laurence Lundblade1341c592020-04-11 14:19:05 -07002283/* Return true if the labels in Item1 and Item2 are the same.
2284 Works only for integer and string labels. Returns false
2285 for any other type. */
2286static inline bool
2287MatchLabel(QCBORItem Item1, QCBORItem Item2)
2288{
2289 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2290 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2291 return true;
2292 }
2293 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002294 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002295 return true;
2296 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002297 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002298 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2299 return true;
2300 }
2301 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2302 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2303 return true;
2304 }
2305 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002306
Laurence Lundblade1341c592020-04-11 14:19:05 -07002307 /* Other label types are never matched */
2308 return false;
2309}
2310
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002311
2312/*
2313 Returns true if Item1 and Item2 are the same type
2314 or if either are of QCBOR_TYPE_ANY.
2315 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002316static inline bool
2317MatchType(QCBORItem Item1, QCBORItem Item2)
2318{
2319 if(Item1.uDataType == Item2.uDataType) {
2320 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002321 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002322 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002323 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002324 return true;
2325 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002326 return false;
2327}
2328
2329
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002330/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002331 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002332
2333 @param[in] pMe The decode context to search.
2334 @param[in,out] pItemArray The items to search for and the items found.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002335 @param[out] puOffset Byte offset of last item matched.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002336 @param[in] pCBContext Context for the not-found item call back
2337 @param[in] pfCallback Function to call on items not matched in pItemArray
2338
2339 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2340
2341 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label) were found for one of the labels being search for. This duplicate detection is only performed for items in pItemArray, not every item in the map.
2342
2343 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2344
2345 @retval Also errors returned by QCBORDecode_GetNext().
2346
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002347 On input pItemArray contains a list of labels and data types
2348 of items to be found.
2349
2350 On output the fully retrieved items are filled in with
2351 values and such. The label was matched, so it never changes.
2352
2353 If an item was not found, its data type is set to none.
2354
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002355 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002356static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002357MapSearch(QCBORDecodeContext *pMe,
2358 QCBORItem *pItemArray,
2359 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002360 void *pCBContext,
2361 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002362{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002363 QCBORError uReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002364
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002365 QCBORDecodeNesting SaveNesting;
2366 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002367
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002368 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
2369 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2370 /* QCBOR_TYPE_NONE as first item indicates just looking
2371 for the end of an array, so don't give error. */
2372 uReturn = QCBOR_ERR_NOT_A_MAP;
2373 goto Done;
2374 }
2375
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002376 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002377 UsefulInputBuf_Seek(&(pMe->InBuf),
2378 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002379
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002380 /*
2381 Loop over all the items in the map. They could be
2382 deeply nested and this should handle both definite
2383 and indefinite length maps and arrays, so this
2384 adds some complexity.
2385 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002386 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002387
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002388 uint_fast8_t uNextNestLevel;
2389
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002390 uint64_t uFoundItemBitMap = 0;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002391
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002392 /* Iterate over items in the map / array */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002393 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002394 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002395 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002396
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002397 /* Get the item */
2398 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002399 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002400 if(uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
2401 /* Zero-length map.
2402 TODO: understand this better. */
2403 break;
2404 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002405 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002406 /* Got non-well-formed CBOR */
2407 goto Done;
2408 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002409
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002410 /* See if item has one of the labels that are of interest */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002411 int nIndex;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002412 QCBORItem *pIterator;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002413 for(pIterator = pItemArray, nIndex = 0; pIterator->uLabelType != 0; pIterator++, nIndex++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002414 if(MatchLabel(Item, *pIterator)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002415 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002416 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2417 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002418 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002419 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002420 /* Also try to match its type */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002421 if(!MatchType(Item, *pIterator)) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002422 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002423 goto Done;
2424 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002425
2426 /* Successful match. Return the item. */
2427 *pIterator = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002428 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002429 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002430 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002431 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002432 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002433 /*
2434 Call the callback on unmatched labels.
2435 (It is tempting to do duplicate detection here, but that would
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002436 require dynamic memory allocation because the number of labels
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002437 that might be encountered is unbounded.)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002438 */
2439 if(pfCallback) {
2440 uReturn = (*pfCallback)(pCBContext, &Item);
2441 if(uReturn != QCBOR_SUCCESS) {
2442 goto Done;
2443 }
2444 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002445 }
2446 }
2447
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002448 /*
2449 Consume the item whether matched or not. This
2450 does the work of traversing maps and array and
2451 everything in them. In this loop only the
2452 items at the current nesting level are examined
2453 to match the labels.
2454 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002455 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2456 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002457 goto Done;
2458 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002459
2460 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002461
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002462 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002463
2464 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002465 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2466 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002467
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002468 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002469 int i;
2470 QCBORItem *pIterator;
2471 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002472 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002473 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002474 }
2475 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002476
2477Done:
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002478 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002479
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002480 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002481}
2482
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002483
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002484/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002485 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002486*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002487void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2488 int64_t nLabel,
2489 uint8_t uQcborType,
2490 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002491{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002492 if(pMe->uLastError != QCBOR_SUCCESS) {
2493 return;
2494 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002495
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002496 QCBORItem OneItemSeach[2];
2497 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2498 OneItemSeach[0].label.int64 = nLabel;
2499 OneItemSeach[0].uDataType = uQcborType;
2500 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002501
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002502 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2503 if(uReturn != QCBOR_SUCCESS) {
2504 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002505 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002506 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002507 uReturn = QCBOR_ERR_NOT_FOUND;
2508 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002509 }
2510
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002511 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002512
2513 Done:
2514 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002515}
2516
2517
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002518/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002519 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002520*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002521void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2522 const char *szLabel,
2523 uint8_t uQcborType,
2524 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002525{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002526 if(pMe->uLastError != QCBOR_SUCCESS) {
2527 return;
2528 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002529
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002530 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002531 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2532 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2533 OneItemSeach[0].uDataType = uQcborType;
2534 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002535
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002536 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2537 if(uReturn != QCBOR_SUCCESS) {
2538 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002539 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002540 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002541 uReturn = QCBOR_ERR_NOT_FOUND;
2542 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002543 }
2544
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002545 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002546
2547Done:
2548 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002549}
2550
2551
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002552
2553static QCBORError CheckTypeList(uint8_t uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
2554{
2555 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2556 if(uDataType == puTypeList[i]) {
2557 return QCBOR_SUCCESS;
2558 }
2559 }
2560 return QCBOR_ERR_UNEXPECTED_TYPE;
2561}
2562
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002563/**
2564 @param[in] TagSpec Specification for matching tags.
2565 @param[in] uDataType A QCBOR data type
2566
2567 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2568 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2569
2570 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2571 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002572static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002573{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002574 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002575 // Must match the tag and only the tag
2576 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002577 }
2578
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002579 QCBORError uReturn = CheckTypeList(uDataType, TagSpec.uAllowedContentTypes);
2580 if(uReturn == QCBOR_SUCCESS) {
2581 return QCBOR_SUCCESS;
2582 }
2583
2584 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
2585 /* Must match the content type and only the content type.
2586 There was no match just above so it is a fail. */
2587 return QCBOR_ERR_UNEXPECTED_TYPE;
2588 }
2589
2590 /* If here it can match either the tag or the content
2591 and it hasn't matched the content, so the end
2592 result is whether it matches the tag. This is
2593 also the case that the CBOR standard discourages. */
2594
2595 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002596}
2597
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002598
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002599// Semi-private
2600// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002601void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2602 int64_t nLabel,
2603 TagSpecification TagSpec,
2604 QCBORItem *pItem)
2605{
2606 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2607 if(pMe->uLastError != QCBOR_SUCCESS) {
2608 return;
2609 }
2610
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002611 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002612}
2613
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002614// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002615void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2616 const char *szLabel,
2617 TagSpecification TagSpec,
2618 QCBORItem *pItem)
2619{
2620 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2621 if(pMe->uLastError != QCBOR_SUCCESS) {
2622 return;
2623 }
2624
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002625 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002626}
2627
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002628// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002629void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2630 int64_t nLabel,
2631 TagSpecification TagSpec,
2632 UsefulBufC *pString)
2633{
2634 QCBORItem Item;
2635 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2636 if(pMe->uLastError == QCBOR_SUCCESS) {
2637 *pString = Item.val.string;
2638 }
2639}
2640
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002641// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002642void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2643 const char * szLabel,
2644 TagSpecification TagSpec,
2645 UsefulBufC *pString)
2646{
2647 QCBORItem Item;
2648 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2649 if(pMe->uLastError == QCBOR_SUCCESS) {
2650 *pString = Item.val.string;
2651 }
2652}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002653
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002654/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002655 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002656*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002657QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2658{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002659 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002660}
2661
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002662/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002663 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002664*/
2665QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2666 QCBORItem *pItemList,
2667 void *pCallbackCtx,
2668 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002669{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002670 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002671}
2672
2673
Laurence Lundblade34691b92020-05-18 22:25:25 -07002674static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002675{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002676 if(pMe->uLastError != QCBOR_SUCCESS) {
2677 // Already in error state; do nothing.
2678 return;
2679 }
2680
2681 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002682 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002683 if(pMe->uLastError != QCBOR_SUCCESS) {
2684 return;
2685 }
2686
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002687 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002688 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002689
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002690 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002691 be at the right place.
2692
2693 The UsefulInBuf offset could be anywhere, so no assumption is
2694 made about it.
2695
2696 No assumption is made about the pre-order nesting level either.
2697
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002698 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002699 the map level that is being entered.
2700 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002701 /* Seek to the data item that is the map or array */
2702 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002703
2704 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002705
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002706 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002707}
2708
2709
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002710/*
2711Public function, see header qcbor/qcbor_decode.h file
2712*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002713void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002714{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002715 QCBORItem OneItemSeach[2];
2716 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2717 OneItemSeach[0].label.int64 = nLabel;
2718 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2719 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002720
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002721 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002722 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002723}
2724
2725
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002726/*
2727Public function, see header qcbor/qcbor_decode.h file
2728*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002729void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002730{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002731 QCBORItem OneItemSeach[2];
2732 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2733 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2734 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2735 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002736
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002737 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002738}
2739
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002740/*
2741Public function, see header qcbor/qcbor_decode.h file
2742*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002743void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002744{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002745 QCBORItem OneItemSeach[2];
2746 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2747 OneItemSeach[0].label.int64 = nLabel;
2748 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2749 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002750
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002751 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002752}
2753
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002754/*
2755Public function, see header qcbor/qcbor_decode.h file
2756*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002757void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2758{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002759 QCBORItem OneItemSeach[2];
2760 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2761 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2762 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2763 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002764
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002765 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002766}
2767
2768
Laurence Lundblade02625d42020-06-25 14:41:41 -07002769// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002770void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002771{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002772 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002773 if(pMe->uLastError != QCBOR_SUCCESS) {
2774 // Already in error state; do nothing.
2775 return;
2776 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002777
2778 /* Get the data item that is the map that is being searched */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002779 QCBORItem Item;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002780 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002781 if(pMe->uLastError != QCBOR_SUCCESS) {
2782 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002783 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002784 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002785 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2786 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002787 }
2788
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002789 if(Item.uNestingLevel == Item.uNextNestLevel) {
2790 // Special case to increment nesting level for zero-length maps and arrays entered in bounded mode.
2791 DecodeNesting_Descend(&(pMe->nesting), uType);
2792 }
2793
Laurence Lundblade02625d42020-06-25 14:41:41 -07002794 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002795
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002796 QCBORError uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting),
2797 UsefulInputBuf_Tell(&(pMe->InBuf)));
2798
2799 pMe->uLastError = (uint8_t)uErr;
2800
Laurence Lundblade02625d42020-06-25 14:41:41 -07002801 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002802}
2803
Laurence Lundblade02625d42020-06-25 14:41:41 -07002804
2805/*
2806 This is for exiting a level that is a bounded map, array or bstr
2807 wrapped CBOR. It is the work common to these.
2808
2809 One chunk of work is to set up the pre-order traversal so it is at
2810 the item just after the bounded map, array or bstr that is being
2811 exited. This is somewhat complex.
2812
2813 The other work is to level-up the bounded mode to next higest bounded
2814 mode or the top level if there isn't one.
2815 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002816static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002817ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002818{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002819 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002820
Laurence Lundblade02625d42020-06-25 14:41:41 -07002821 /*
2822 First the pre-order-traversal byte offset is positioned to the
2823 item just after the bounded mode item that was just consumed.
2824 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002825 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2826
Laurence Lundblade02625d42020-06-25 14:41:41 -07002827 /*
2828 Next, set the current nesting level to one above the bounded level
2829 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002830
Laurence Lundblade02625d42020-06-25 14:41:41 -07002831 DecodeNesting_CheckBoundedType() is always called before this and
2832 makes sure pCurrentBounded is valid.
2833 */
2834 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2835
2836 /*
2837 This does the complex work of leveling up the pre-order traversal
2838 when the end of a map or array or another bounded level is
2839 reached. It may do nothing, or ascend all the way to the top
2840 level.
2841 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07002842 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002843 if(uErr != QCBOR_SUCCESS) {
2844 goto Done;
2845 }
2846
Laurence Lundblade02625d42020-06-25 14:41:41 -07002847 /*
2848 This makes the next highest bounded level the current bounded
2849 level. If there is no next highest level, then no bounded mode is
2850 in effect.
2851 */
2852 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002853
Laurence Lundblade02625d42020-06-25 14:41:41 -07002854 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002855
2856Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002857 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002858 return uErr;
2859}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002860
Laurence Lundblade02625d42020-06-25 14:41:41 -07002861
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002862// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002863void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002864{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002865 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002866 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002867 return;
2868 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002869
Laurence Lundblade02625d42020-06-25 14:41:41 -07002870 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002871
Laurence Lundblade02625d42020-06-25 14:41:41 -07002872 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002873 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2874 goto Done;
2875 }
2876
Laurence Lundblade02625d42020-06-25 14:41:41 -07002877 /*
2878 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002879 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002880 from previous map search, then do a dummy search.
2881 */
2882 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002883 QCBORItem Dummy;
2884 Dummy.uLabelType = QCBOR_TYPE_NONE;
2885 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2886 if(uErr != QCBOR_SUCCESS) {
2887 goto Done;
2888 }
2889 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002890
Laurence Lundblade02625d42020-06-25 14:41:41 -07002891 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002892
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002893Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002894 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002895}
2896
2897
Laurence Lundblade1341c592020-04-11 14:19:05 -07002898void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002899{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002900 // TODO: check for map mode; test this
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002901 //pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->u.ma.uCountTotal;
2902 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->u.ma.uStartOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002903}
2904
2905
Laurence Lundblade1341c592020-04-11 14:19:05 -07002906
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002907static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002908 const QCBORItem *pItem,
2909 uint8_t uTagRequirement,
2910 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002911{
2912 if(pMe->uLastError != QCBOR_SUCCESS) {
2913 // Already in error state; do nothing.
2914 return pMe->uLastError;
2915 }
2916
2917 QCBORError uError = QCBOR_SUCCESS;
2918
2919 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2920 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2921 goto Done;;
2922 }
2923
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002924 const TagSpecification TagSpec = {uTagRequirement,
2925 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
2926 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
2927 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002928
2929 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2930 if(uError != QCBOR_SUCCESS) {
2931 goto Done;
2932 }
2933
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002934 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002935 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002936 so the increment in NestLevelAscender called by ExitBoundedLevel()
2937 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002938 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002939 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002940
2941 if(pBstr) {
2942 *pBstr = pItem->val.string;
2943 }
2944
2945 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002946
2947 // Need to move UIB input cursor to the right place
2948
2949 // Really this is a subtraction and an assignment; not much code
2950 // There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002951 // The bstr was just consumed so the cursor is at the next item after it
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002952
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002953 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002954
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002955 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
2956
2957 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002958
Laurence Lundblade02625d42020-06-25 14:41:41 -07002959 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
2960 uPreviousLength,
2961 uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002962Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002963 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002964
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002965 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002966}
2967
2968
Laurence Lundblade02625d42020-06-25 14:41:41 -07002969/*
2970 Public function, see header qcbor/qcbor_decode.h file
2971 */
2972void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002973 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002974 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002975{
2976 if(pMe->uLastError != QCBOR_SUCCESS) {
2977 // Already in error state; do nothing.
2978 return;
2979 }
2980
2981 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002982 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002983 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
2984 if(pMe->uLastError != QCBOR_SUCCESS) {
2985 return;
2986 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002987
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002988 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002989 &Item,
2990 uTagRequirement,
2991 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002992}
2993
2994
Laurence Lundblade02625d42020-06-25 14:41:41 -07002995/*
2996 Public function, see header qcbor/qcbor_decode.h file
2997 */
2998void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
2999 uint8_t uTagRequirement,
3000 int64_t nLabel,
3001 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003002{
3003 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003004 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003005
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003006 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003007}
3008
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003009
Laurence Lundblade02625d42020-06-25 14:41:41 -07003010/*
3011 Public function, see header qcbor/qcbor_decode.h file
3012 */
3013void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
3014 uint8_t uTagRequirement,
3015 const char *szLabel,
3016 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003017{
3018 QCBORItem Item;
3019 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3020
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003021 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003022}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003023
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003024
Laurence Lundblade02625d42020-06-25 14:41:41 -07003025/*
3026 Public function, see header qcbor/qcbor_decode.h file
3027 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003028void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003029{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003030 if(pMe->uLastError != QCBOR_SUCCESS) {
3031 // Already in error state; do nothing.
3032 return;
3033 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003034
Laurence Lundblade02625d42020-06-25 14:41:41 -07003035 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3036 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3037 return;
3038 }
3039
3040 /*
3041 Reset the length of the UsefulInputBuf to what it was before
3042 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003043 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003044 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3045 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003046
3047
Laurence Lundblade02625d42020-06-25 14:41:41 -07003048 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003049 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003050}
3051
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003052
Laurence Lundbladee6430642020-03-14 21:15:44 -07003053
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003054
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003055
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003056
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003057
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003058
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003059static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3060{
3061 switch(pItem->uDataType) {
3062 case QCBOR_TYPE_TRUE:
3063 *pBool = true;
3064 return QCBOR_SUCCESS;
3065 break;
3066
3067 case QCBOR_TYPE_FALSE:
3068 *pBool = false;
3069 return QCBOR_SUCCESS;
3070 break;
3071
3072 default:
3073 return QCBOR_ERR_UNEXPECTED_TYPE;
3074 break;
3075 }
3076}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003077
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003078/*
3079Public function, see header qcbor/qcbor_decode.h file
3080*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003081void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003082{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003083 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003084 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003085 return;
3086 }
3087
Laurence Lundbladec4537442020-04-14 18:53:22 -07003088 QCBORError nError;
3089 QCBORItem Item;
3090
3091 nError = QCBORDecode_GetNext(pMe, &Item);
3092 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003093 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003094 return;
3095 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003096 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003097}
3098
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003099/*
3100Public function, see header qcbor/qcbor_decode.h file
3101*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003102void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003103{
3104 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003105 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003106
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003107 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003108}
3109
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003110/*
3111Public function, see header qcbor/qcbor_decode.h file
3112*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003113void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3114{
3115 QCBORItem Item;
3116 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3117
3118 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3119}
3120
3121
3122
3123void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003124{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003125 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003126 // Already in error state, do nothing
3127 return;
3128 }
3129
3130 QCBORError nError;
3131 QCBORItem Item;
3132
3133 nError = QCBORDecode_GetNext(pMe, &Item);
3134 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003135 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003136 return;
3137 }
3138
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003139 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3140
3141 if(pMe->uLastError == QCBOR_SUCCESS) {
3142 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003143 }
3144}
3145
Laurence Lundbladec4537442020-04-14 18:53:22 -07003146
3147
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003148
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003149static QCBORError ConvertBigNum(uint8_t uTagRequirement,
3150 const QCBORItem *pItem,
3151 UsefulBufC *pValue,
3152 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003153{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003154 const TagSpecification TagSpec = {uTagRequirement,
3155 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3156 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3157 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003158
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003159 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
3160 if(uErr != QCBOR_SUCCESS) {
3161 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003162 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003163
3164 *pValue = pItem->val.string;
3165
3166 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3167 *pbIsNegative = false;
3168 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3169 *pbIsNegative = true;
3170 }
3171
3172 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003173}
3174
3175
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003176/**
3177 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003178 */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003179void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003180{
3181 if(pMe->uLastError != QCBOR_SUCCESS) {
3182 // Already in error state, do nothing
3183 return;
3184 }
3185
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003186 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003187 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3188 if(uError != QCBOR_SUCCESS) {
3189 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003190 return;
3191 }
3192
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003193 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003194}
3195
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003196/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003197Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003198*/
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003199void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003200{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003201 QCBORItem Item;
3202 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003203
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003204 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003205}
3206
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003207/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003208Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003209*/
3210void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
3211{
3212 QCBORItem Item;
3213 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3214
3215 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
3216}
3217
3218
3219
3220// Semi private
3221QCBORError FarfMIME(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsNot7Bit)
3222{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003223
3224
3225 const TagSpecification TagSpecText = {uTagRequirement,
3226 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3227 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3228 };
3229 const TagSpecification TagSpecBinary = {uTagRequirement,
3230 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3231 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3232 };
3233
3234
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003235 QCBORError uReturn;
3236
3237 if(CheckTagRequirement(TagSpecText, pItem->uDataType)) {
3238 *pMessage = pItem->val.string;
3239 if(pbIsNot7Bit != NULL) {
3240 *pbIsNot7Bit = false;
3241 }
3242 uReturn = QCBOR_SUCCESS;
3243 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType)) {
3244 *pMessage = pItem->val.string;
3245 if(pbIsNot7Bit != NULL) {
3246 *pbIsNot7Bit = true;
3247 }
3248 uReturn = QCBOR_SUCCESS;
3249
3250 } else {
3251 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3252 }
3253
3254 return uReturn;
3255}
3256
3257
3258
3259
3260
Laurence Lundbladec4537442020-04-14 18:53:22 -07003261
3262
3263
Laurence Lundbladee6430642020-03-14 21:15:44 -07003264
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003265typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003266
3267
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003268// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003269static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003270{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003271 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003272
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003273 if(uResult != 0) {
3274 /* This loop will run a maximum of 19 times because
3275 * UINT64_MAX < 10 ^^ 19. More than that will cause
3276 * exit with the overflow error
3277 */
3278 for(; nExponent > 0; nExponent--) {
3279 if(uResult > UINT64_MAX / 10) {
3280 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3281 }
3282 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003283 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003284
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003285 for(; nExponent < 0; nExponent++) {
3286 uResult = uResult / 10;
3287 if(uResult == 0) {
3288 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3289 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003290 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003291 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003292 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003293
3294 *puResult = uResult;
3295
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003296 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003297}
3298
3299
Laurence Lundbladee6430642020-03-14 21:15:44 -07003300/* Convert a decimal fraction to an int64_t without using
3301 floating point or math libraries. Most decimal fractions
3302 will not fit in an int64_t and this will error out with
3303 under or overflow
3304 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003305static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003306{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003307 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003308
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003309 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003310
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003311 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003312 * INT64_MAX < 2^31. More than that will cause
3313 * exist with the overflow error
3314 */
3315 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003316 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003317 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003318 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003319 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003320 nExponent--;
3321 }
3322
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003323 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003324 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003325 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3326 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003327 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003328 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003329 }
3330
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003331 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003332
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003333 return QCBOR_SUCCESS;
3334}
3335
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003336/*
3337 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3338 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003339static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3340{
3341 uint64_t uResult;
3342
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003343 // Take the absolute value of the mantissa and convert to unsigned.
3344 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003345 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3346
3347 // Do the exponentiation of the positive mantissa
3348 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3349 if(uReturn) {
3350 return uReturn;
3351 }
3352
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003353
Laurence Lundblade983500d2020-05-14 11:49:34 -07003354 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3355 of INT64_MIN. This assumes two's compliment representation where
3356 INT64_MIN is one increment farther from 0 than INT64_MAX.
3357 Trying to write -INT64_MIN doesn't work to get this because the
3358 compiler tries to work with an int64_t which can't represent
3359 -INT64_MIN.
3360 */
3361 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3362
3363 // Error out if too large
3364 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003365 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3366 }
3367
3368 // Casts are safe because of checks above
3369 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3370
3371 return QCBOR_SUCCESS;
3372}
3373
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003374/*
3375 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3376 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003377static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3378{
3379 if(nMantissa < 0) {
3380 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3381 }
3382
3383 // Cast to unsigned is OK because of check for negative
3384 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3385 // Exponentiation is straight forward
3386 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3387}
3388
3389
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003390#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003391
3392
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003393static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003394{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003395 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003396
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003397 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003398 const uint8_t *pByte = BigNum.ptr;
3399 size_t uLen = BigNum.len;
3400 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003401 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003402 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003403 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003404 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003405 }
3406
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003407 *pResult = uResult;
3408 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003409}
3410
Laurence Lundblade887add82020-05-17 05:50:34 -07003411static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003412{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003413 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003414}
3415
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003416static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003417{
3418 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003419 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3420 if(uError) {
3421 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003422 }
3423 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3424 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003425 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003426}
3427
3428
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003429static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003430{
3431 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003432 /* negaative int furthest from zero is INT64_MIN
3433 which is expressed as -INT64_MAX-1. The value of
3434 a negative bignum is -n-1, one further from zero
3435 than the positive bignum */
3436
3437 /* say INT64_MIN is -2; then INT64_MAX is 1.
3438 Then -n-1 <= INT64_MIN.
3439 Then -n -1 <= -INT64_MAX - 1
3440 THen n <= INT64_MAX. */
3441 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003442 if(uError) {
3443 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003444 }
3445 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003446 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003447 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003448 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003449 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003450}
3451
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003452#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003453
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003454
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003455/*
3456Convert a integers and floats to an int64_t.
3457
3458\param[in] uOptions Bit mask list of conversion options.
3459
3460\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3461
3462\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3463
3464\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3465
3466*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003467static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3468{
3469 switch(pItem->uDataType) {
3470 // TODO: float when ifdefs are set
3471 case QCBOR_TYPE_DOUBLE:
3472 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3473 // TODO: what about under/overflow here?
3474 // Invokes the floating-point HW and/or compiler-added libraries
3475 feclearexcept(FE_ALL_EXCEPT);
3476 *pnValue = llround(pItem->val.dfnum);
3477 if(fetestexcept(FE_INVALID)) {
3478 // TODO: better error code
3479 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3480 }
3481 } else {
3482 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3483 }
3484 break;
3485
3486 case QCBOR_TYPE_INT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003487 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003488 *pnValue = pItem->val.int64;
3489 } else {
3490 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3491 }
3492 break;
3493
3494 case QCBOR_TYPE_UINT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003495 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003496 if(pItem->val.uint64 < INT64_MAX) {
3497 *pnValue = pItem->val.int64;
3498 } else {
3499 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3500 }
3501 } else {
3502 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3503 }
3504 break;
3505
3506 default:
3507 return QCBOR_ERR_UNEXPECTED_TYPE;
3508 }
3509 return QCBOR_SUCCESS;
3510}
3511
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003512
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003513void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
3514 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003515 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003516 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003517{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003518 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003519 return;
3520 }
3521
Laurence Lundbladee6430642020-03-14 21:15:44 -07003522 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003523 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3524 if(uError) {
3525 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003526 return;
3527 }
3528
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003529 if(pItem) {
3530 *pItem = Item;
3531 }
3532
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003533 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003534}
3535
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003536
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003537void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3538 int64_t nLabel,
3539 uint32_t uOptions,
3540 int64_t *pnValue,
3541 QCBORItem *pItem)
3542{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003543 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003544 if(pMe->uLastError != QCBOR_SUCCESS) {
3545 return;
3546 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003547
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003548 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003549}
3550
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003551
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003552void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3553 const char * szLabel,
3554 uint32_t uOptions,
3555 int64_t *pnValue,
3556 QCBORItem *pItem)
3557{
3558 if(pMe->uLastError != QCBOR_SUCCESS) {
3559 return;
3560 }
3561
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003562 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003563 if(pMe->uLastError != QCBOR_SUCCESS) {
3564 return;
3565 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003566
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003567 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003568}
3569
3570
3571
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003572/*
3573 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003574
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003575 \param[in] uOptions Bit mask list of conversion options.
3576
3577 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3578
3579 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3580
3581 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3582
3583 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003584static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3585{
3586 QCBORError uErr;
3587
3588 switch(pItem->uDataType) {
3589
3590 case QCBOR_TYPE_POSBIGNUM:
3591 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3592 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003593 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003594 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003595 }
3596 break;
3597
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003598 case QCBOR_TYPE_NEGBIGNUM:
3599 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3600 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003601 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003602 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003603 }
3604 break;
3605
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003606#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3607 case QCBOR_TYPE_DECIMAL_FRACTION:
3608 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3609 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3610 pItem->val.expAndMantissa.nExponent,
3611 pnValue,
3612 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003613 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003614 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3615 }
3616 break;
3617
3618 case QCBOR_TYPE_BIGFLOAT:
3619 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3620 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3621 pItem->val.expAndMantissa.nExponent,
3622 pnValue,
3623 Exponentitate2);
3624 } else {
3625 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3626 }
3627 break;
3628
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003629 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3630 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3631 int64_t nMantissa;
3632 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3633 if(uErr) {
3634 return uErr;
3635 }
3636 return ExponentiateNN(nMantissa,
3637 pItem->val.expAndMantissa.nExponent,
3638 pnValue,
3639 Exponentitate10);
3640 } else {
3641 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3642 }
3643 break;
3644
3645 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3646 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3647 int64_t nMantissa;
3648 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3649 if(uErr) {
3650 return uErr;
3651 }
3652 return ExponentiateNN(nMantissa,
3653 pItem->val.expAndMantissa.nExponent,
3654 pnValue,
3655 Exponentitate10);
3656 } else {
3657 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3658 }
3659 break;
3660
3661 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3662 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3663 int64_t nMantissa;
3664 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3665 if(uErr) {
3666 return uErr;
3667 }
3668 return ExponentiateNN(nMantissa,
3669 pItem->val.expAndMantissa.nExponent,
3670 pnValue,
3671 Exponentitate2);
3672 } else {
3673 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3674 }
3675 break;
3676
3677 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3678 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3679 int64_t nMantissa;
3680 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3681 if(uErr) {
3682 return uErr;
3683 }
3684 return ExponentiateNN(nMantissa,
3685 pItem->val.expAndMantissa.nExponent,
3686 pnValue,
3687 Exponentitate2);
3688 } else {
3689 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003690 }
3691 break;
3692
Laurence Lundbladec4537442020-04-14 18:53:22 -07003693 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003694 return QCBOR_ERR_UNEXPECTED_TYPE;
3695#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07003696 }
3697}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003698
3699
Laurence Lundbladec4537442020-04-14 18:53:22 -07003700/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003701 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003702 */
3703void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003704{
3705 QCBORItem Item;
3706
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003707 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003708
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003709 if(pMe->uLastError == QCBOR_SUCCESS) {
3710 // The above conversion succeeded
3711 return;
3712 }
3713
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003714 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003715 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003716 return;
3717 }
3718
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003719 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003720}
3721
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003722
3723/*
3724Public function, see header qcbor/qcbor_decode.h file
3725*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003726void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
3727{
3728 QCBORItem Item;
3729
3730 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
3731
3732 if(pMe->uLastError == QCBOR_SUCCESS) {
3733 // The above conversion succeeded
3734 return;
3735 }
3736
3737 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3738 // The above conversion failed in a way that code below can't correct
3739 return;
3740 }
3741
3742 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3743}
3744
3745
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003746/*
3747Public function, see header qcbor/qcbor_decode.h file
3748*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003749void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3750{
3751 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003752 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3753
3754 if(pMe->uLastError == QCBOR_SUCCESS) {
3755 // The above conversion succeeded
3756 return;
3757 }
3758
3759 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3760 // The above conversion failed in a way that code below can't correct
3761 return;
3762 }
3763
3764 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3765}
3766
3767
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003768static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3769{
3770 switch(pItem->uDataType) {
3771 // TODO: type flaot
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07003772 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003773 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3774 feclearexcept(FE_ALL_EXCEPT);
3775 double dRounded = round(pItem->val.dfnum);
3776 // TODO: over/underflow
3777 if(fetestexcept(FE_INVALID)) {
3778 // TODO: better error code
3779 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3780 } else if(isnan(dRounded)) {
3781 // TODO: better error code
3782 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3783 } else if(dRounded >= 0) {
3784 *puValue = (uint64_t)dRounded;
3785 } else {
3786 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3787 }
3788 } else {
3789 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3790 }
3791 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003792
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003793 case QCBOR_TYPE_INT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003794 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003795 if(pItem->val.int64 >= 0) {
3796 *puValue = (uint64_t)pItem->val.int64;
3797 } else {
3798 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3799 }
3800 } else {
3801 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3802 }
3803 break;
3804
3805 case QCBOR_TYPE_UINT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003806 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003807 *puValue = pItem->val.uint64;
3808 } else {
3809 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3810 }
3811 break;
3812
3813 default:
3814 return QCBOR_ERR_UNEXPECTED_TYPE;
3815 }
3816 return QCBOR_SUCCESS;
3817}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003818
3819
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003820void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3821 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003822 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003823 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003824{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003825 if(pMe->uLastError != QCBOR_SUCCESS) {
3826 return;
3827 }
3828
Laurence Lundbladec4537442020-04-14 18:53:22 -07003829 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003830
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003831 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3832 if(uError) {
3833 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003834 return;
3835 }
3836
Laurence Lundbladea826c502020-05-10 21:07:00 -07003837 if(pItem) {
3838 *pItem = Item;
3839 }
3840
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003841 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003842}
3843
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003844
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003845void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3846{
3847 int64_t uValue;
3848 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, &uValue, pItem);
3849 if(pMe->uLastError != QCBOR_SUCCESS) {
3850 return;
3851 }
3852
3853 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3854 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3855 }
3856}
3857
3858void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3859{
3860 int64_t uValue;
3861 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, &uValue, pItem);
3862 if(pMe->uLastError != QCBOR_SUCCESS) {
3863 return;
3864 }
3865
3866 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3867 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3868 }
3869}
3870
3871void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3872{
3873 int64_t uValue;
3874 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, &uValue, pItem);
3875 if(pMe->uLastError != QCBOR_SUCCESS) {
3876 return;
3877 }
3878
3879 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3880 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3881 }
3882}
3883
3884
3885
3886
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003887void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3888 int64_t nLabel,
3889 uint32_t uOptions,
3890 uint64_t *puValue,
3891 QCBORItem *pItem)
3892{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003893 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003894 if(pMe->uLastError != QCBOR_SUCCESS) {
3895 return;
3896 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003897
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003898 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uOptions, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003899}
3900
3901
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003902void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003903 const char * szLabel,
3904 uint32_t uOptions,
3905 uint64_t *puValue,
3906 QCBORItem *pItem)
3907{
3908 if(pMe->uLastError != QCBOR_SUCCESS) {
3909 return;
3910 }
3911
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003912 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003913 if(pMe->uLastError != QCBOR_SUCCESS) {
3914 return;
3915 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003916
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003917 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uOptions, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003918}
3919
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003920/*
3921 Public function, see header qcbor/qcbor_decode.h file
3922*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003923static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3924{
3925 QCBORError uErr;
3926
3927 switch(pItem->uDataType) {
3928
3929 case QCBOR_TYPE_POSBIGNUM:
3930 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3931 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3932 } else {
3933 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3934 }
3935 break;
3936
3937 case QCBOR_TYPE_NEGBIGNUM:
3938 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3939 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3940 } else {
3941 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3942 }
3943 break;
3944
3945#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3946
3947 case QCBOR_TYPE_DECIMAL_FRACTION:
3948 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3949 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3950 pItem->val.expAndMantissa.nExponent,
3951 puValue,
3952 Exponentitate10);
3953 } else {
3954 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3955 }
3956 break;
3957
3958 case QCBOR_TYPE_BIGFLOAT:
3959 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3960 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3961 pItem->val.expAndMantissa.nExponent,
3962 puValue,
3963 Exponentitate2);
3964 } else {
3965 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3966 }
3967 break;
3968
3969 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3970 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3971 // TODO: Would be better to convert to unsigned
3972 int64_t nMantissa;
3973 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3974 if(uErr != QCBOR_SUCCESS) {
3975 return uErr;
3976 }
3977 return ExponentitateNU(nMantissa,
3978 pItem->val.expAndMantissa.nExponent,
3979 puValue,
3980 Exponentitate10);
3981 } else {
3982 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3983 }
3984 break;
3985
3986 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3987 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3988 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3989 } else {
3990 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3991 }
3992 break;
3993
3994 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3995 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3996 // TODO: Would be better to convert to unsigned
3997 int64_t nMantissa;
3998 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3999 if(uErr != QCBOR_SUCCESS) {
4000 return uErr;
4001 }
4002 return ExponentitateNU(nMantissa,
4003 pItem->val.expAndMantissa.nExponent,
4004 puValue,
4005 Exponentitate2);
4006 } else {
4007 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4008 }
4009 break;
4010
4011 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4012 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4013 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4014 } else {
4015 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4016 }
4017 break;
4018#endif
4019 default:
4020 return QCBOR_ERR_UNEXPECTED_TYPE;
4021 }
4022}
4023
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004024/*
4025 Public function, see header qcbor/qcbor_decode.h file
4026*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004027void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004028{
4029 QCBORItem Item;
4030
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004031 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004032
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004033 if(pMe->uLastError == QCBOR_SUCCESS) {
4034 // The above conversion succeeded
4035 return;
4036 }
4037
4038 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4039 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004040 return;
4041 }
4042
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004043 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004044}
4045
Laurence Lundbladec4537442020-04-14 18:53:22 -07004046
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004047/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004048 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004049*/
4050void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
4051{
4052 QCBORItem Item;
4053
4054 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
4055
4056 if(pMe->uLastError == QCBOR_SUCCESS) {
4057 // The above conversion succeeded
4058 return;
4059 }
4060
4061 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4062 // The above conversion failed in a way that code below can't correct
4063 return;
4064 }
4065
4066 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4067}
4068
4069
4070/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004071 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004072*/
4073void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
4074{
4075 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004076 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004077
4078 if(pMe->uLastError == QCBOR_SUCCESS) {
4079 // The above conversion succeeded
4080 return;
4081 }
4082
4083 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4084 // The above conversion failed in a way that code below can't correct
4085 return;
4086 }
4087
4088 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4089}
4090
4091
4092static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
4093{
4094 switch(pItem->uDataType) {
4095 // TODO: float when ifdefs are set
4096 case QCBOR_TYPE_DOUBLE:
4097 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4098 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4099 *pdValue = pItem->val.dfnum;
4100 } else {
4101 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4102 }
4103 }
4104 break;
4105
4106 case QCBOR_TYPE_INT64:
4107 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
4108 // TODO: how does this work?
4109 *pdValue = (double)pItem->val.int64;
4110
4111 } else {
4112 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4113 }
4114 break;
4115
4116 case QCBOR_TYPE_UINT64:
4117 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
4118 *pdValue = (double)pItem->val.uint64;
4119 } else {
4120 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4121 }
4122 break;
4123
4124 default:
4125 return QCBOR_ERR_UNEXPECTED_TYPE;
4126 }
4127
4128 return QCBOR_SUCCESS;
4129}
4130
4131
4132
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004133void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
4134 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004135 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004136 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004137{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004138 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004139 return;
4140 }
4141
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004142 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004143
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004144 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004145 if(uError) {
4146 pMe->uLastError = (uint8_t)uError;
4147 return;
4148 }
4149
4150 if(pItem) {
4151 *pItem = Item;
4152 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004153
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004154 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004155}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004156
Laurence Lundbladec4537442020-04-14 18:53:22 -07004157
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004158void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4159 int64_t nLabel,
4160 uint32_t uOptions,
4161 double *pdValue,
4162 QCBORItem *pItem)
4163{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004164 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004165 if(pMe->uLastError != QCBOR_SUCCESS) {
4166 return;
4167 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004168
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004169 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uOptions, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004170}
4171
4172void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4173 const char * szLabel,
4174 uint32_t uOptions,
4175 double *pdValue,
4176 QCBORItem *pItem)
4177{
4178 if(pMe->uLastError != QCBOR_SUCCESS) {
4179 return;
4180 }
4181
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004182 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004183 if(pMe->uLastError != QCBOR_SUCCESS) {
4184 return;
4185 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004186
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004187 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uOptions, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004188}
4189
4190
4191
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004192static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4193{
4194 double dResult;
4195
4196 dResult = 0.0;
4197 const uint8_t *pByte = BigNum.ptr;
4198 size_t uLen = BigNum.len;
4199 /* This will overflow and become the float value INFINITY if the number
4200 is too large to fit. No error will be logged.
4201 TODO: should an error be logged? */
4202 while(uLen--) {
4203 dResult = (dResult * 256.0) + (double)*pByte++;
4204 }
4205
4206 return dResult;
4207}
4208
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004209static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004210{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004211 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004212 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4213
4214 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004215 switch(pItem->uDataType) {
4216 // TODO: type float
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004217
4218#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004219 case QCBOR_TYPE_DECIMAL_FRACTION:
4220 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4221 // TODO: rounding and overflow errors
4222 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4223 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4224 } else {
4225 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4226 }
4227 break;
4228
4229 case QCBOR_TYPE_BIGFLOAT:
4230 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
4231 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4232 exp2((double)pItem->val.expAndMantissa.nExponent);
4233 } else {
4234 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4235 }
4236 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004237#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004238
4239 case QCBOR_TYPE_POSBIGNUM:
4240 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
4241 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4242 } else {
4243 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4244 }
4245 break;
4246
4247 case QCBOR_TYPE_NEGBIGNUM:
4248 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004249 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004250 } else {
4251 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4252 }
4253 break;
4254
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004255#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004256 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4257 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4258 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4259 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4260 } else {
4261 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4262 }
4263 break;
4264
4265 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4266 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4267 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4268 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4269 } else {
4270 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4271 }
4272 break;
4273
4274 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4275 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
4276 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4277 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4278 } else {
4279 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4280 }
4281 break;
4282
4283 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4284 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004285 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004286 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4287 } else {
4288 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4289 }
4290 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004291#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4292
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004293
4294 default:
4295 return QCBOR_ERR_UNEXPECTED_TYPE;
4296 }
4297
4298 return QCBOR_SUCCESS;
4299}
4300
4301
4302/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004303 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004304*/
4305void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
4306{
4307
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004308 QCBORItem Item;
4309
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004310 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004311
4312 if(pMe->uLastError == QCBOR_SUCCESS) {
4313 // The above conversion succeeded
4314 return;
4315 }
4316
4317 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4318 // The above conversion failed in a way that code below can't correct
4319 return;
4320 }
4321
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004322 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004323}
4324
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004325
4326/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004327 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004328*/
4329void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
4330{
4331 QCBORItem Item;
4332
4333 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
4334
4335 if(pMe->uLastError == QCBOR_SUCCESS) {
4336 // The above conversion succeeded
4337 return;
4338 }
4339
4340 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4341 // The above conversion failed in a way that code below can't correct
4342 return;
4343 }
4344
4345 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4346}
4347
4348
4349/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004350 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004351*/
4352void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
4353{
4354 QCBORItem Item;
4355 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
4356
4357 if(pMe->uLastError == QCBOR_SUCCESS) {
4358 // The above conversion succeeded
4359 return;
4360 }
4361
4362 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4363 // The above conversion failed in a way that code below can't correct
4364 return;
4365 }
4366
4367 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4368}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004369
4370
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004371#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004372static void ProcessDecimalFraction(QCBORDecodeContext *pMe,
4373 uint8_t uTagRequirement,
4374 QCBORItem *pItem,
4375 int64_t *pnMantissa,
4376 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004377{
4378 QCBORError uErr;
4379
4380 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004381
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004382 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4383 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4384 return;
4385 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004386 /* The decimal fraction was untagged so it shows up as an
4387 array at this point. We are called to interpret it
4388 as a decimal fraction, so do protocol decoding. If
4389 it was tagged, iw would shouw up here with the
4390 QCBOR_TYPE_DECIMAL_FRACTION or such. */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004391 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4392 if(uErr != QCBOR_SUCCESS) {
4393 pMe->uLastError = (uint8_t)uErr;
4394 return;
4395 }
4396 }
4397
4398 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4399 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4400 return;
4401 }
4402
4403 switch (pItem->uDataType) {
4404
4405 case QCBOR_TYPE_DECIMAL_FRACTION:
4406 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4407 *pnExponent = pItem->val.expAndMantissa.nExponent;
4408 break;
4409
4410 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4411 *pnExponent = pItem->val.expAndMantissa.nExponent;
4412
4413 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4414 if(uErr != QCBOR_SUCCESS) {
4415 pMe->uLastError = (uint8_t)uErr;
4416 }
4417 break;
4418
4419 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4420 *pnExponent = pItem->val.expAndMantissa.nExponent;
4421
4422 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4423 if(uErr != QCBOR_SUCCESS) {
4424 pMe->uLastError = (uint8_t)uErr;
4425 }
4426 break;
4427
4428 default:
4429 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4430 }
4431}
4432
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004433
4434void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
4435 uint8_t uTagRequirement,
4436 int64_t *pnMantissa,
4437 int64_t *pnExponent)
4438{
4439 if(pMe->uLastError != QCBOR_SUCCESS) {
4440 return;
4441 }
4442
4443 QCBORItem Item;
4444 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4445 if(uError) {
4446 pMe->uLastError = (uint8_t)uError;
4447 return;
4448 }
4449
4450 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4451}
4452
4453
4454void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004455 uint8_t uTagRequirement,
4456 int64_t nLabel,
4457 int64_t *pnMantissa,
4458 int64_t *pnExponent)
4459{
4460 QCBORItem Item;
4461
4462 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004463 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004464}
4465
4466
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004467void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
4468 uint8_t uTagRequirement,
4469 const char *szLabel,
4470 int64_t *pnMantissa,
4471 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004472{
4473 QCBORItem Item;
4474
4475 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4476
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004477 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004478}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004479#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004480
4481
4482UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4483{
4484 while(uInt & 0xff0000000000UL) {
4485 uInt = uInt << 8;
4486 };
4487
4488 UsefulOutBuf UOB;
4489
4490 UsefulOutBuf_Init(&UOB, Buffer);
4491
4492 while(uInt) {
4493 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56));
4494 uInt = uInt << 8;
4495 }
4496
4497 return UsefulOutBuf_OutUBuf(&UOB);
4498}
4499
4500
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004501#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4502
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004503static void ProcessDecimalFractionBig(QCBORDecodeContext *pMe,
4504 uint8_t uTagRequirement,
4505 QCBORItem *pItem,
4506 UsefulBuf BufferForMantissa,
4507 UsefulBufC *pMantissa,
4508 bool *pbIsNegative,
4509 int64_t *pnExponent)
4510{
4511
4512 const TagSpecification TagSpec = {uTagRequirement,
4513 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4514 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4515 };
4516
4517 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
4518 if(uErr != QCBOR_SUCCESS) {
4519 pMe->uLastError = (uint8_t)uErr;
4520 return;
4521 }
4522
4523 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
4524 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4525 if(uErr != QCBOR_SUCCESS) {
4526 pMe->uLastError = (uint8_t)uErr;
4527 return;
4528 }
4529 }
4530
4531 uint64_t uMantissa;
4532
4533 switch (pItem->uDataType) {
4534
4535 case QCBOR_TYPE_DECIMAL_FRACTION:
4536 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
4537 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
4538 *pbIsNegative = false;
4539 } else {
4540 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
4541 *pbIsNegative = true;
4542 }
4543 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
4544 *pnExponent = pItem->val.expAndMantissa.nExponent;
4545 break;
4546
4547 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4548 *pnExponent = pItem->val.expAndMantissa.nExponent;
4549 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4550 *pbIsNegative = false;
4551 break;
4552
4553 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4554 *pnExponent = pItem->val.expAndMantissa.nExponent;
4555 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4556 *pbIsNegative = true;
4557 break;
4558
4559 default:
4560 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4561 }
4562}
4563
4564
4565void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
4566 uint8_t uTagRequirement,
4567 UsefulBuf MantissaBuffer,
4568 UsefulBufC *pMantissa,
4569 bool *pbMantissaIsNegative,
4570 int64_t *pnExponent)
4571{
4572
4573 if(pMe->uLastError != QCBOR_SUCCESS) {
4574 return;
4575 }
4576
4577 QCBORItem Item;
4578 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4579 if(uError) {
4580 pMe->uLastError = (uint8_t)uError;
4581 return;
4582 }
4583
4584 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
4585
4586}
4587
4588void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
4589 uint8_t uTagRequirement,
4590 int64_t nLabel,
4591 UsefulBuf BufferForMantissa,
4592 UsefulBufC *pMantissa,
4593 bool *pbIsNegative,
4594 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004595{
4596 QCBORItem Item;
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004597
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004598 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004599 if(pMe->uLastError != QCBOR_SUCCESS) {
4600 return;
4601 }
4602
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004603 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
4604}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004605
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004606
4607void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
4608 uint8_t uTagRequirement,
4609 const char *szLabel,
4610 UsefulBuf BufferForMantissa,
4611 UsefulBufC *pMantissa,
4612 bool *pbIsNegative,
4613 int64_t *pnExponent)
4614{
4615 QCBORItem Item;
4616
4617 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4618 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004619 return;
4620 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004621
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004622 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004623}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004624
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004625#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004626
4627/*
4628
4629 TODO: do something with this text
4630 The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...)
4631 formed by intermediate nodes (arrays and maps). The cursor for the traversal
4632 is the byte offset in the encoded input and a leaf counter for definite
4633 length maps and arrays. Indefinite length maps and arrays are handled
4634 by look ahead for the break.
4635
4636 The view presented to the caller has tags, labels and the chunks of
4637 indefinite length strings aggregated into one decorated data item.
4638
4639 The caller understands the nesting level in pre-order traversal by
4640 the fact that a data item that is a map or array is presented to
4641 the caller when it is first encountered in the pre-order traversal and that all data items are presented with its nesting level
4642 and the nesting level of the next item.
4643
4644 The caller traverse maps and arrays in a special mode that often more convenient
4645 that tracking by nesting level. When an array or map is expected or encountered
4646 the EnterMap or EnteryArray can be called.
4647
4648 When entering a map or array like this, the cursor points to the first
4649 item in the map or array. When exiting, it points to the item after
4650 the map or array, regardless of whether the items in the map or array were
4651 all traversed.
4652
4653 When in a map or array, the cursor functions as normal, but traversal
4654 cannot go past the end of the map or array that was entered. If this
4655 is attempted the QCBOR_ERR_NO_MORE_ITEMS error is returned. To
4656 go past the end of the map or array ExitMap() or ExitArray() must
4657 be called. It can be called any time regardless of the position
4658 of the cursor.
4659
4660 When a map is entered, a special function allows fetching data items
4661 by label. This call will traversal the whole map looking for the
4662 labeled item. The whole map is traversed so as to detect duplicates.
4663 This type of fetching items does not affect the normal traversal
4664 cursor.
4665
4666
4667 When a data item is presented to the caller, the nesting level of the data
4668 item is presented along with the nesting level of the item that would be
4669 next consumed.
4670 */