blob: 511de13aaf72de7d9dea87b5f84b82fa48c2f4ff [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
282DecodeNesting_Decsend(QCBORDecodeNesting *pNesting, uint8_t uType)
283{
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 Lundblade02625d42020-06-25 14:41:41 -0700339 uError = DecodeNesting_Decsend(pNesting, uQCBORType);
340 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700341 goto Done;
342 }
343
Laurence Lundblade02625d42020-06-25 14:41:41 -0700344 // Fill in the new map/array level. Check above makes cast 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 Lundblade02625d42020-06-25 14:41:41 -0700387 uError = DecodeNesting_Decsend(pNesting, QCBOR_TYPE_BYTE_STRING);
388 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 Lundblade642282a2020-06-23 12:00:33 -07001359 This the travesal going descending into and asecnding out of maps,
1360 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 Lundblade24d509a2020-06-06 18:43:15 -07001379
Laurence Lundblade642282a2020-06-23 12:00:33 -07001380 Only return the success error code QCBOR_ERR_NO_MORE_ITEMS here
1381 when at the top level to allow other code below to process various
1382 errors when out of bytes to decode and not at the top level. Note
1383 that QCBORDecode_Finish() still needs to be called to be sure all
1384 nesting levels were closed out.
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001385
1386 TODO: really check for top level here?
Laurence Lundblade642282a2020-06-23 12:00:33 -07001387 */
1388 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 &&
1389 DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001390 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001391 goto Done;
1392 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001393
Laurence Lundblade642282a2020-06-23 12:00:33 -07001394 /*
1395 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001396 array. The check for the end of an indefinite length array is
1397 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001398 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001399 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001400 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001401 goto Done;
1402 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001403
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001404 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001405 uReturn = GetNext_MapEntry(me, pDecodedItem);
1406 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001407 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001408 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301409
Laurence Lundblade642282a2020-06-23 12:00:33 -07001410 /*
1411 Breaks ending arrays/maps are always processed at the end of this
1412 function. They should never show up here.
1413 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301414 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001415 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301416 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301417 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001418
Laurence Lundblade642282a2020-06-23 12:00:33 -07001419 /*
1420 Record the nesting level for this data item before processing any
1421 of decrementing and descending.
1422 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001423 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001424
Laurence Lundblade642282a2020-06-23 12:00:33 -07001425
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001426 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001427 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001428 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001429 If the new item is a map or array descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001430
Laurence Lundblade02625d42020-06-25 14:41:41 -07001431 Empty maps and arrays descended into, but then ascended out
1432 of in the next chunk of code.
1433
1434 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001435 encloses them so a decrement needs to be done for them too, but
1436 that is done only when all the items in them have been
1437 processed, not when they are opened with the exception of an
1438 empty map or array.
1439 */
1440 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1441 pDecodedItem->uDataType,
1442 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001443 if(uReturn != QCBOR_SUCCESS) {
1444 goto Done;
1445 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001446 }
1447
Laurence Lundblade02625d42020-06-25 14:41:41 -07001448 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1449 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1450 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001451 /*
1452 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001453 - A non-aggregate like an integer or string
1454 - An empty definite length map or array
1455 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001456
1457 The Ascender does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001458 definite length map/array and break detection for an indefinite
1459 length map/array. If the end of the map/array was reached, then
1460 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001461 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001462 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001463 if(uReturn) {
1464 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001465 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301466 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001467
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001468 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001469 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001470 Tell the caller what level is next. This tells them what
1471 maps/arrays were closed out and makes it possible for them to
1472 reconstruct the tree with just the information returned in
1473 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001474 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001475 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001476 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001477 pDecodedItem->uNextNestLevel = 0;
1478 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001479 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001480 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001481
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001482Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001483 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001484 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001485 memset(pDecodedItem, 0, sizeof(QCBORItem));
1486 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001487 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001488}
1489
1490
Laurence Lundblade59289e52019-12-30 13:44:37 -08001491/*
1492 Mostly just assign the right data type for the date string.
1493 */
1494inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1495{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001496 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1497 return QCBOR_ERR_BAD_OPT_TAG;
1498 }
1499
1500 const UsefulBufC Temp = pDecodedItem->val.string;
1501 pDecodedItem->val.dateString = Temp;
1502 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1503 return QCBOR_SUCCESS;
1504}
1505
1506
1507/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001508 The epoch formatted date. Turns lots of different forms of encoding
1509 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001510 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001511static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001512{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001513 QCBORError nReturn = QCBOR_SUCCESS;
1514
1515 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1516
1517 switch (pDecodedItem->uDataType) {
1518
1519 case QCBOR_TYPE_INT64:
1520 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1521 break;
1522
1523 case QCBOR_TYPE_UINT64:
1524 if(pDecodedItem->val.uint64 > INT64_MAX) {
1525 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1526 goto Done;
1527 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001528 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001529 break;
1530
1531 case QCBOR_TYPE_DOUBLE:
1532 {
1533 // This comparison needs to be done as a float before
1534 // conversion to an int64_t to be able to detect doubles
1535 // that are too large to fit into an int64_t. A double
1536 // has 52 bits of preceision. An int64_t has 63. Casting
1537 // INT64_MAX to a double actually causes a round up which
1538 // is bad and wrong for the comparison because it will
1539 // allow conversion of doubles that can't fit into a
1540 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1541 // the cutoff point as if that rounds up in conversion to
1542 // double it will still be less than INT64_MAX. 0x7ff is
1543 // picked because it has 11 bits set.
1544 //
1545 // INT64_MAX seconds is on the order of 10 billion years,
1546 // and the earth is less than 5 billion years old, so for
1547 // most uses this conversion error won't occur even though
1548 // doubles can go much larger.
1549 //
1550 // Without the 0x7ff there is a ~30 minute range of time
1551 // values 10 billion years in the past and in the future
1552 // where this this code would go wrong.
1553 const double d = pDecodedItem->val.dfnum;
1554 if(d > (double)(INT64_MAX - 0x7ff)) {
1555 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1556 goto Done;
1557 }
1558 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1559 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1560 }
1561 break;
1562
1563 default:
1564 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1565 goto Done;
1566 }
1567 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1568
1569Done:
1570 return nReturn;
1571}
1572
1573
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001574/*
1575 Mostly just assign the right data type for the bignum.
1576 */
1577inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1578{
1579 // Stack Use: UsefulBuf 1 -- 16
1580 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1581 return QCBOR_ERR_BAD_OPT_TAG;
1582 }
1583 const UsefulBufC Temp = pDecodedItem->val.string;
1584 pDecodedItem->val.bigNum = Temp;
1585 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1586 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1587 : QCBOR_TYPE_NEGBIGNUM);
1588 return QCBOR_SUCCESS;
1589}
1590
1591
Laurence Lundblade59289e52019-12-30 13:44:37 -08001592#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1593/*
1594 Decode decimal fractions and big floats.
1595
1596 When called pDecodedItem must be the array that is tagged as a big
1597 float or decimal fraction, the array that has the two members, the
1598 exponent and mantissa.
1599
1600 This will fetch and decode the exponent and mantissa and put the
1601 result back into pDecodedItem.
1602 */
1603inline static QCBORError
1604QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1605{
1606 QCBORError nReturn;
1607
1608 // --- Make sure it is an array; track nesting level of members ---
1609 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1610 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1611 goto Done;
1612 }
1613
1614 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001615 // definite length arrays, but not for indefnite. Instead remember
1616 // the nesting level the two integers must be at, which is one
1617 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001618 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1619
1620 // --- Is it a decimal fraction or a bigfloat? ---
1621 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1622 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1623
1624 // --- Get the exponent ---
1625 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001626 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001627 if(nReturn != QCBOR_SUCCESS) {
1628 goto Done;
1629 }
1630 if(exponentItem.uNestingLevel != nNestLevel) {
1631 // Array is empty or a map/array encountered when expecting an int
1632 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1633 goto Done;
1634 }
1635 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1636 // Data arriving as an unsigned int < INT64_MAX has been converted
1637 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1638 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1639 // will be too large for this to handle and thus an error that will
1640 // get handled in the next else.
1641 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1642 } else {
1643 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1644 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1645 goto Done;
1646 }
1647
1648 // --- Get the mantissa ---
1649 QCBORItem mantissaItem;
1650 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1651 if(nReturn != QCBOR_SUCCESS) {
1652 goto Done;
1653 }
1654 if(mantissaItem.uNestingLevel != nNestLevel) {
1655 // Mantissa missing or map/array encountered when expecting number
1656 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1657 goto Done;
1658 }
1659 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1660 // Data arriving as an unsigned int < INT64_MAX has been converted
1661 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1662 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1663 // will be too large for this to handle and thus an error that
1664 // will get handled in an else below.
1665 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1666 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1667 // Got a good big num mantissa
1668 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1669 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001670 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1671 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1672 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001673 } else {
1674 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1675 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1676 goto Done;
1677 }
1678
1679 // --- Check that array only has the two numbers ---
1680 if(mantissaItem.uNextNestLevel == nNestLevel) {
1681 // Extra items in the decimal fraction / big num
1682 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1683 goto Done;
1684 }
1685
1686Done:
1687
1688 return nReturn;
1689}
1690#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1691
1692
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001693
1694/*
1695 */
1696inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1697{
1698 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1699 return QCBOR_ERR_BAD_OPT_TAG;
1700 }
1701 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1702 return QCBOR_SUCCESS;
1703}
1704
1705
1706inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1707{
1708 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1709 return QCBOR_ERR_BAD_OPT_TAG;
1710 }
1711 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1712 return QCBOR_SUCCESS;
1713}
1714
1715
1716inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1717{
1718 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1719 return QCBOR_ERR_BAD_OPT_TAG;
1720 }
1721 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1722 return QCBOR_SUCCESS;
1723}
1724
1725
1726inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1727{
1728 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1729 return QCBOR_ERR_BAD_OPT_TAG;
1730 }
1731 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1732 return QCBOR_SUCCESS;
1733}
1734
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001735inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1736{
1737 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1738 return QCBOR_ERR_BAD_OPT_TAG;
1739 }
1740 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1741 return QCBOR_SUCCESS;
1742}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001743
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001744
1745inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1746{
1747 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1748 return QCBOR_ERR_BAD_OPT_TAG;
1749 }
1750 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
1751 return QCBOR_SUCCESS;
1752}
1753
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001754inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1755{
1756 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1757 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
1758 } else if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1759 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1760 } else {
1761 return QCBOR_ERR_BAD_OPT_TAG;
1762 }
1763 return QCBOR_SUCCESS;
1764}
1765
1766
1767/*
1768 */
1769inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1770{
1771 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1772 return QCBOR_ERR_BAD_OPT_TAG;
1773 }
1774 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1775 return QCBOR_SUCCESS;
1776}
1777
1778
Laurence Lundblade59289e52019-12-30 13:44:37 -08001779/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001780 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001781 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001782QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001783QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001784{
1785 QCBORError nReturn;
1786
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001787 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001788 if(nReturn != QCBOR_SUCCESS) {
1789 goto Done;
1790 }
1791
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001792 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1793 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001794
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001795 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001796 nReturn = DecodeDateString(pDecodedItem);
1797 break;
1798
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001799 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001800 nReturn = DecodeDateEpoch(pDecodedItem);
1801 break;
1802
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001803 case CBOR_TAG_POS_BIGNUM:
1804 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001805 nReturn = DecodeBigNum(pDecodedItem);
1806 break;
1807
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001808 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1809 case CBOR_TAG_DECIMAL_FRACTION:
1810 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001811 // For aggregate tagged types, what goes into pTags is only collected
1812 // from the surrounding data item, not the contents, so pTags is not
1813 // passed on here.
1814
1815 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1816 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001817 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001818
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001819 case CBOR_TAG_CBOR:
1820 nReturn = DecodeWrappedCBOR(pDecodedItem);
1821 break;
1822
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001823 case CBOR_TAG_CBOR_SEQUENCE:
1824 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1825 break;
1826
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001827 case CBOR_TAG_URI:
1828 nReturn = DecodeURI(pDecodedItem);
1829 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001830
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001831 case CBOR_TAG_B64URL:
1832 nReturn = DecodeB64URL(pDecodedItem);
1833 break;
1834
1835 case CBOR_TAG_B64:
1836 nReturn = DecodeB64(pDecodedItem);
1837 break;
1838
1839 case CBOR_TAG_MIME:
1840 case CBOR_TAG_BINARY_MIME:
1841 nReturn = DecodeMIME(pDecodedItem);
1842 break;
1843
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001844 case CBOR_TAG_REGEX:
1845 nReturn = DecodeRegex(pDecodedItem);
1846 break;
1847
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001848 case CBOR_TAG_BIN_UUID:
1849 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001850 break;
1851
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001852 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001853 // The end of the tag list or no tags
1854 // Successful exit from the loop.
1855 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001856
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001857 default:
1858 // A tag that is not understood
1859 // A successful exit from the loop
1860 goto Done;
1861
1862 }
1863 if(nReturn != QCBOR_SUCCESS) {
1864 goto Done;
1865 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001866 }
1867
1868Done:
1869 if(nReturn != QCBOR_SUCCESS) {
1870 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1871 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1872 }
1873 return nReturn;
1874}
1875
1876
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001877QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1878{
1879 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1880
1881 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1882
1883 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1884
1885 return uErr;
1886}
1887
1888
Laurence Lundblade59289e52019-12-30 13:44:37 -08001889/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001890 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001891 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001892QCBORError
1893QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1894 QCBORItem *pDecodedItem,
1895 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001896{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001897 QCBORError nReturn;
1898
1899 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1900 if(nReturn != QCBOR_SUCCESS) {
1901 return nReturn;
1902 }
1903
1904 if(pTags != NULL) {
1905 pTags->uNumUsed = 0;
1906 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001907 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001908 break;
1909 }
1910 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1911 return QCBOR_ERR_TOO_MANY_TAGS;
1912 }
1913 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1914 pTags->uNumUsed++;
1915 }
1916 }
1917
1918 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001919}
1920
1921
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001922/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301923 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301924 next one down. If a layer has no work to do for a particular item
1925 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001926
Laurence Lundblade59289e52019-12-30 13:44:37 -08001927 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1928 tagged data items, turning them into the local C representation.
1929 For the most simple it is just associating a QCBOR_TYPE with the data. For
1930 the complex ones that an aggregate of data items, there is some further
1931 decoding and a little bit of recursion.
1932
1933 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301934 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301935 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001936 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001937
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301938 - GetNext_MapEntry -- This handles the combining of two
1939 items, the label and the data, that make up a map entry.
1940 It only does work on maps. It combines the label and data
1941 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001942
Laurence Lundblade59289e52019-12-30 13:44:37 -08001943 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1944 tags into bit flags associated with the data item. No actual decoding
1945 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001946
Laurence Lundblade59289e52019-12-30 13:44:37 -08001947 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301948 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301949 string allocater to create contiguous space for the item. It
1950 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001951
Laurence Lundblade59289e52019-12-30 13:44:37 -08001952 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1953 atomic data item has a "major type", an integer "argument" and optionally
1954 some content. For text and byte strings, the content is the bytes
1955 that make up the string. These are the smallest data items that are
1956 considered to be well-formed. The content may also be other data items in
1957 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001958
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001959 Roughly this takes 300 bytes of stack for vars. Need to
1960 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001961
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301962 */
1963
1964
1965/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001966 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001967 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001968int QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001969 const QCBORItem *pItem,
1970 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001971{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001972 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001973 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001974 break;
1975 }
1976 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1977 return 1;
1978 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001979 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001980
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001981 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001982}
1983
1984
1985/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001986 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001987 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001988QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001989{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001990 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001991
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001992 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001993 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001994 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1995 goto Done;
1996 }
1997
1998 // Error out if not all the bytes are consumed
1999 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
2000 nReturn = QCBOR_ERR_EXTRA_BYTES;
2001 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002002
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002003Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302004 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002005 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002006 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002007
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002008 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002009}
2010
2011
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002012/*
2013Public function, see header qcbor/qcbor_decode.h file
2014*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002015uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2016 const QCBORItem *pItem,
2017 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002018{
2019 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
2020 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002021 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002022 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002023 }
2024}
2025
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002026
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002027/*
2028
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002029Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002030
Laurence Lundbladeee851742020-01-08 08:37:05 -08002031 - Hit end of input before it was expected while decoding type and
2032 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002033
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002034 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002035
Laurence Lundbladeee851742020-01-08 08:37:05 -08002036 - Hit end of input while decoding a text or byte string
2037 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002038
Laurence Lundbladeee851742020-01-08 08:37:05 -08002039 - Encountered conflicting tags -- e.g., an item is tagged both a date
2040 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002041
Laurence Lundbladeee851742020-01-08 08:37:05 -08002042 - Encontered an array or mapp that has too many items
2043 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002044
Laurence Lundbladeee851742020-01-08 08:37:05 -08002045 - Encountered array/map nesting that is too deep
2046 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002047
Laurence Lundbladeee851742020-01-08 08:37:05 -08002048 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2049 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002050
Laurence Lundbladeee851742020-01-08 08:37:05 -08002051 - The type of a map label is not a string or int
2052 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002053
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002054 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002055
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002056 */
2057
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002058
2059
Laurence Lundbladef6531662018-12-04 10:42:22 +09002060
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002061/* ===========================================================================
2062 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002063
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002064 This implements a simple sting allocator for indefinite length
2065 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2066 implements the function type QCBORStringAllocate and allows easy
2067 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002068
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002069 This particular allocator is built-in for convenience. The caller
2070 can implement their own. All of this following code will get
2071 dead-stripped if QCBORDecode_SetMemPool() is not called.
2072
2073 This is a very primitive memory allocator. It does not track
2074 individual allocations, only a high-water mark. A free or
2075 reallocation must be of the last chunk allocated.
2076
2077 The size of the pool and offset to free memory are packed into the
2078 first 8 bytes of the memory pool so we don't have to keep them in
2079 the decode context. Since the address of the pool may not be
2080 aligned, they have to be packed and unpacked as if they were
2081 serialized data of the wire or such.
2082
2083 The sizes packed in are uint32_t to be the same on all CPU types
2084 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002085 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002086
2087
Laurence Lundbladeee851742020-01-08 08:37:05 -08002088static inline int
2089MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002090{
2091 // Use of UsefulInputBuf is overkill, but it is convenient.
2092 UsefulInputBuf UIB;
2093
Laurence Lundbladeee851742020-01-08 08:37:05 -08002094 // Just assume the size here. It was checked during SetUp so
2095 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002096 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2097 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2098 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2099 return UsefulInputBuf_GetError(&UIB);
2100}
2101
2102
Laurence Lundbladeee851742020-01-08 08:37:05 -08002103static inline int
2104MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002105{
2106 // Use of UsefulOutBuf is overkill, but convenient. The
2107 // length check performed here is useful.
2108 UsefulOutBuf UOB;
2109
2110 UsefulOutBuf_Init(&UOB, Pool);
2111 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2112 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2113 return UsefulOutBuf_GetError(&UOB);
2114}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002115
2116
2117/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002118 Internal function for an allocation, reallocation free and destuct.
2119
2120 Having only one function rather than one each per mode saves space in
2121 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002122
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002123 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2124 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002125static UsefulBuf
2126MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002127{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002128 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002129
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002130 uint32_t uPoolSize;
2131 uint32_t uFreeOffset;
2132
2133 if(uNewSize > UINT32_MAX) {
2134 // This allocator is only good up to 4GB. This check should
2135 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2136 goto Done;
2137 }
2138 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2139
2140 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2141 goto Done;
2142 }
2143
2144 if(uNewSize) {
2145 if(pMem) {
2146 // REALLOCATION MODE
2147 // Calculate pointer to the end of the memory pool. It is
2148 // assumed that pPool + uPoolSize won't wrap around by
2149 // assuming the caller won't pass a pool buffer in that is
2150 // not in legitimate memory space.
2151 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2152
2153 // Check that the pointer for reallocation is in the range of the
2154 // pool. This also makes sure that pointer math further down
2155 // doesn't wrap under or over.
2156 if(pMem >= pPool && pMem < pPoolEnd) {
2157 // Offset to start of chunk for reallocation. This won't
2158 // wrap under because of check that pMem >= pPool. Cast
2159 // is safe because the pool is always less than UINT32_MAX
2160 // because of check in QCBORDecode_SetMemPool().
2161 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2162
2163 // Check to see if the allocation will fit. uPoolSize -
2164 // uMemOffset will not wrap under because of check that
2165 // pMem is in the range of the uPoolSize by check above.
2166 if(uNewSize <= uPoolSize - uMemOffset) {
2167 ReturnValue.ptr = pMem;
2168 ReturnValue.len = uNewSize;
2169
2170 // Addition won't wrap around over because uNewSize was
2171 // checked to be sure it is less than the pool size.
2172 uFreeOffset = uMemOffset + uNewSize32;
2173 }
2174 }
2175 } else {
2176 // ALLOCATION MODE
2177 // uPoolSize - uFreeOffset will not underflow because this
2178 // pool implementation makes sure uFreeOffset is always
2179 // smaller than uPoolSize through this check here and
2180 // reallocation case.
2181 if(uNewSize <= uPoolSize - uFreeOffset) {
2182 ReturnValue.len = uNewSize;
2183 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002184 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002185 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002186 }
2187 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002188 if(pMem) {
2189 // FREE MODE
2190 // Cast is safe because of limit on pool size in
2191 // QCBORDecode_SetMemPool()
2192 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2193 } else {
2194 // DESTRUCT MODE
2195 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002196 }
2197 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002198
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002199 UsefulBuf Pool = {pPool, uPoolSize};
2200 MemPool_Pack(Pool, uFreeOffset);
2201
2202Done:
2203 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002204}
2205
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002206
Laurence Lundbladef6531662018-12-04 10:42:22 +09002207/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002208 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002209 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002210QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2211 UsefulBuf Pool,
2212 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002213{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002214 // The pool size and free mem offset are packed into the beginning
2215 // of the pool memory. This compile time check make sure the
2216 // constant in the header is correct. This check should optimize
2217 // down to nothing.
2218 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002219 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002220 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002221
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002222 // The pool size and free offset packed in to the beginning of pool
2223 // memory are only 32-bits. This check will optimize out on 32-bit
2224 // machines.
2225 if(Pool.len > UINT32_MAX) {
2226 return QCBOR_ERR_BUFFER_TOO_LARGE;
2227 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002228
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002229 // This checks that the pool buffer given is big enough.
2230 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2231 return QCBOR_ERR_BUFFER_TOO_SMALL;
2232 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002233
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002234 pMe->StringAllocator.pfAllocator = MemPool_Function;
2235 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2236 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002237
Laurence Lundblade30816f22018-11-10 13:40:22 +07002238 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002239}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002240
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002241
2242
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002243
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002244
2245
2246/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002247 Consume an entire map or array (and do next to
2248 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002249 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002250static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002251ConsumeItem(QCBORDecodeContext *pMe,
2252 const QCBORItem *pItemToConsume,
2253 uint_fast8_t *puNextNestLevel)
2254{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002255 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002256 QCBORItem Item;
2257
Laurence Lundblade02625d42020-06-25 14:41:41 -07002258 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002259
Laurence Lundblade02625d42020-06-25 14:41:41 -07002260 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002261 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002262
Laurence Lundblade1341c592020-04-11 14:19:05 -07002263 /* This works for definite and indefinite length
2264 * maps and arrays by using the nesting level
2265 */
2266 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002267 uReturn = QCBORDecode_GetNext(pMe, &Item);
2268 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002269 goto Done;
2270 }
2271 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002272
Laurence Lundblade1341c592020-04-11 14:19:05 -07002273 if(puNextNestLevel != NULL) {
2274 *puNextNestLevel = Item.uNextNestLevel;
2275 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002276 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002277
Laurence Lundblade1341c592020-04-11 14:19:05 -07002278 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002279 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002280 if(puNextNestLevel != NULL) {
2281 /* Just pass the nesting level through */
2282 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2283 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002284 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002285 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002286
2287Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002288 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002289}
2290
2291
Laurence Lundblade1341c592020-04-11 14:19:05 -07002292/* Return true if the labels in Item1 and Item2 are the same.
2293 Works only for integer and string labels. Returns false
2294 for any other type. */
2295static inline bool
2296MatchLabel(QCBORItem Item1, QCBORItem Item2)
2297{
2298 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2299 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2300 return true;
2301 }
2302 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002303 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002304 return true;
2305 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002306 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002307 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2308 return true;
2309 }
2310 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2311 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2312 return true;
2313 }
2314 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002315
Laurence Lundblade1341c592020-04-11 14:19:05 -07002316 /* Other label types are never matched */
2317 return false;
2318}
2319
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002320
2321/*
2322 Returns true if Item1 and Item2 are the same type
2323 or if either are of QCBOR_TYPE_ANY.
2324 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002325static inline bool
2326MatchType(QCBORItem Item1, QCBORItem Item2)
2327{
2328 if(Item1.uDataType == Item2.uDataType) {
2329 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002330 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002331 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002332 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002333 return true;
2334 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002335 return false;
2336}
2337
2338
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002339/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002340 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002341
2342 @param[in] pMe The decode context to search.
2343 @param[in,out] pItemArray The items to search for and the items found.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002344 @param[out] puOffset Byte offset of last item matched.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002345 @param[in] pCBContext Context for the not-found item call back
2346 @param[in] pfCallback Function to call on items not matched in pItemArray
2347
2348 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2349
2350 @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.
2351
2352 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2353
2354 @retval Also errors returned by QCBORDecode_GetNext().
2355
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002356 On input pItemArray contains a list of labels and data types
2357 of items to be found.
2358
2359 On output the fully retrieved items are filled in with
2360 values and such. The label was matched, so it never changes.
2361
2362 If an item was not found, its data type is set to none.
2363
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002364 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002365static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002366MapSearch(QCBORDecodeContext *pMe,
2367 QCBORItem *pItemArray,
2368 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002369 void *pCBContext,
2370 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002371{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002372 QCBORError uReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002373
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002374 QCBORDecodeNesting SaveNesting;
2375 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002376
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002377 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
2378 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2379 /* QCBOR_TYPE_NONE as first item indicates just looking
2380 for the end of an array, so don't give error. */
2381 uReturn = QCBOR_ERR_NOT_A_MAP;
2382 goto Done;
2383 }
2384
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002385 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002386 UsefulInputBuf_Seek(&(pMe->InBuf),
2387 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002388
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002389 /*
2390 Loop over all the items in the map. They could be
2391 deeply nested and this should handle both definite
2392 and indefinite length maps and arrays, so this
2393 adds some complexity.
2394 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002395 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002396
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002397 uint_fast8_t uNextNestLevel;
2398
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002399 uint64_t uFoundItemBitMap = 0;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002400
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002401 /* Iterate over items in the map / array */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002402 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002403 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002404 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002405
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002406 /* Get the item */
2407 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002408 uReturn = QCBORDecode_GetNext(pMe, &Item);
2409 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002410 /* Got non-well-formed CBOR */
2411 goto Done;
2412 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002413
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002414 /* See if item has one of the labels that are of interest */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002415 int nIndex;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002416 QCBORItem *pIterator;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002417 for(pIterator = pItemArray, nIndex = 0; pIterator->uLabelType != 0; pIterator++, nIndex++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002418 if(MatchLabel(Item, *pIterator)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002419 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002420 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2421 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002422 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002423 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002424 /* Also try to match its type */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002425 if(!MatchType(Item, *pIterator)) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002426 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002427 goto Done;
2428 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002429
2430 /* Successful match. Return the item. */
2431 *pIterator = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002432 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002433 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002434 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002435 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002436 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002437 /*
2438 Call the callback on unmatched labels.
2439 (It is tempting to do duplicate detection here, but that would
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002440 require dynamic memory allocation because the number of labels
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002441 that might be encountered is unbounded.)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002442 */
2443 if(pfCallback) {
2444 uReturn = (*pfCallback)(pCBContext, &Item);
2445 if(uReturn != QCBOR_SUCCESS) {
2446 goto Done;
2447 }
2448 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002449 }
2450 }
2451
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002452 /*
2453 Consume the item whether matched or not. This
2454 does the work of traversing maps and array and
2455 everything in them. In this loop only the
2456 items at the current nesting level are examined
2457 to match the labels.
2458 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002459 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2460 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002461 goto Done;
2462 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002463
2464 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002465
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002466 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002467
2468 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002469 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2470 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002471
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002472 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002473 int i;
2474 QCBORItem *pIterator;
2475 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002476 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002477 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002478 }
2479 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002480
2481Done:
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002482 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002483
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002484 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002485}
2486
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002487
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002488/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002489 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002490*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002491void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2492 int64_t nLabel,
2493 uint8_t uQcborType,
2494 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002495{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002496 if(pMe->uLastError != QCBOR_SUCCESS) {
2497 return;
2498 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002499
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002500 QCBORItem OneItemSeach[2];
2501 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2502 OneItemSeach[0].label.int64 = nLabel;
2503 OneItemSeach[0].uDataType = uQcborType;
2504 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002505
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002506 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2507 if(uReturn != QCBOR_SUCCESS) {
2508 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002509 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002510 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002511 uReturn = QCBOR_ERR_NOT_FOUND;
2512 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002513 }
2514
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002515 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002516
2517 Done:
2518 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002519}
2520
2521
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002522/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002523 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002524*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002525void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2526 const char *szLabel,
2527 uint8_t uQcborType,
2528 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002529{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002530 if(pMe->uLastError != QCBOR_SUCCESS) {
2531 return;
2532 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002533
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002534 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002535 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2536 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2537 OneItemSeach[0].uDataType = uQcborType;
2538 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002539
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002540 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2541 if(uReturn != QCBOR_SUCCESS) {
2542 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002543 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002544 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002545 uReturn = QCBOR_ERR_NOT_FOUND;
2546 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002547 }
2548
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002549 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002550
2551Done:
2552 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002553}
2554
2555
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002556
2557static QCBORError CheckTypeList(uint8_t uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
2558{
2559 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2560 if(uDataType == puTypeList[i]) {
2561 return QCBOR_SUCCESS;
2562 }
2563 }
2564 return QCBOR_ERR_UNEXPECTED_TYPE;
2565}
2566
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002567/**
2568 @param[in] TagSpec Specification for matching tags.
2569 @param[in] uDataType A QCBOR data type
2570
2571 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2572 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2573
2574 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2575 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002576static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002577{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002578 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002579 // Must match the tag and only the tag
2580 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002581 }
2582
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002583 QCBORError uReturn = CheckTypeList(uDataType, TagSpec.uAllowedContentTypes);
2584 if(uReturn == QCBOR_SUCCESS) {
2585 return QCBOR_SUCCESS;
2586 }
2587
2588 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
2589 /* Must match the content type and only the content type.
2590 There was no match just above so it is a fail. */
2591 return QCBOR_ERR_UNEXPECTED_TYPE;
2592 }
2593
2594 /* If here it can match either the tag or the content
2595 and it hasn't matched the content, so the end
2596 result is whether it matches the tag. This is
2597 also the case that the CBOR standard discourages. */
2598
2599 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002600}
2601
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002602
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002603// Semi-private
2604// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002605void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2606 int64_t nLabel,
2607 TagSpecification TagSpec,
2608 QCBORItem *pItem)
2609{
2610 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2611 if(pMe->uLastError != QCBOR_SUCCESS) {
2612 return;
2613 }
2614
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002615 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002616}
2617
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002618// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002619void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2620 const char *szLabel,
2621 TagSpecification TagSpec,
2622 QCBORItem *pItem)
2623{
2624 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2625 if(pMe->uLastError != QCBOR_SUCCESS) {
2626 return;
2627 }
2628
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002629 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002630}
2631
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002632// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002633void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2634 int64_t nLabel,
2635 TagSpecification TagSpec,
2636 UsefulBufC *pString)
2637{
2638 QCBORItem Item;
2639 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2640 if(pMe->uLastError == QCBOR_SUCCESS) {
2641 *pString = Item.val.string;
2642 }
2643}
2644
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002645// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002646void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2647 const char * szLabel,
2648 TagSpecification TagSpec,
2649 UsefulBufC *pString)
2650{
2651 QCBORItem Item;
2652 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2653 if(pMe->uLastError == QCBOR_SUCCESS) {
2654 *pString = Item.val.string;
2655 }
2656}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002657
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002658/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002659 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002660*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002661QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2662{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002663 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002664}
2665
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002666/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002667 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002668*/
2669QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2670 QCBORItem *pItemList,
2671 void *pCallbackCtx,
2672 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002673{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002674 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002675}
2676
2677
Laurence Lundblade34691b92020-05-18 22:25:25 -07002678static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002679{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002680 if(pMe->uLastError != QCBOR_SUCCESS) {
2681 // Already in error state; do nothing.
2682 return;
2683 }
2684
2685 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002686 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002687 if(pMe->uLastError != QCBOR_SUCCESS) {
2688 return;
2689 }
2690
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002691 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002692 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002693
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002694 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002695 be at the right place.
2696
2697 The UsefulInBuf offset could be anywhere, so no assumption is
2698 made about it.
2699
2700 No assumption is made about the pre-order nesting level either.
2701
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002702 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002703 the map level that is being entered.
2704 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002705 /* Seek to the data item that is the map or array */
2706 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002707
2708 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002709
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002710 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002711}
2712
2713
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002714/*
2715Public function, see header qcbor/qcbor_decode.h file
2716*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002717void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002718{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002719 QCBORItem OneItemSeach[2];
2720 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2721 OneItemSeach[0].label.int64 = nLabel;
2722 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2723 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002724
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002725 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002726 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002727}
2728
2729
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002730/*
2731Public function, see header qcbor/qcbor_decode.h file
2732*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002733void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002734{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002735 QCBORItem OneItemSeach[2];
2736 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2737 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2738 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2739 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002740
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002741 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002742}
2743
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002744/*
2745Public function, see header qcbor/qcbor_decode.h file
2746*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002747void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002748{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002749 QCBORItem OneItemSeach[2];
2750 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2751 OneItemSeach[0].label.int64 = nLabel;
2752 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2753 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002754
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002755 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002756}
2757
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002758/*
2759Public function, see header qcbor/qcbor_decode.h file
2760*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002761void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2762{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002763 QCBORItem OneItemSeach[2];
2764 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2765 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2766 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2767 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002768
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002769 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002770}
2771
2772
Laurence Lundblade02625d42020-06-25 14:41:41 -07002773// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002774void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002775{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002776 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002777 if(pMe->uLastError != QCBOR_SUCCESS) {
2778 // Already in error state; do nothing.
2779 return;
2780 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002781
2782 /* Get the data item that is the map that is being searched */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002783 QCBORItem Item;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002784 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002785 if(pMe->uLastError != QCBOR_SUCCESS) {
2786 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002787 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002788 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002789 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2790 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002791 }
2792
Laurence Lundblade02625d42020-06-25 14:41:41 -07002793 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002794
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002795 QCBORError uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting),
2796 UsefulInputBuf_Tell(&(pMe->InBuf)));
2797
2798 pMe->uLastError = (uint8_t)uErr;
2799
Laurence Lundblade02625d42020-06-25 14:41:41 -07002800 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002801}
2802
Laurence Lundblade02625d42020-06-25 14:41:41 -07002803
2804/*
2805 This is for exiting a level that is a bounded map, array or bstr
2806 wrapped CBOR. It is the work common to these.
2807
2808 One chunk of work is to set up the pre-order traversal so it is at
2809 the item just after the bounded map, array or bstr that is being
2810 exited. This is somewhat complex.
2811
2812 The other work is to level-up the bounded mode to next higest bounded
2813 mode or the top level if there isn't one.
2814 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002815static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002816ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002817{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002818 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002819
Laurence Lundblade02625d42020-06-25 14:41:41 -07002820 /*
2821 First the pre-order-traversal byte offset is positioned to the
2822 item just after the bounded mode item that was just consumed.
2823 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002824 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2825
Laurence Lundblade02625d42020-06-25 14:41:41 -07002826 /*
2827 Next, set the current nesting level to one above the bounded level
2828 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002829
Laurence Lundblade02625d42020-06-25 14:41:41 -07002830 DecodeNesting_CheckBoundedType() is always called before this and
2831 makes sure pCurrentBounded is valid.
2832 */
2833 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2834
2835 /*
2836 This does the complex work of leveling up the pre-order traversal
2837 when the end of a map or array or another bounded level is
2838 reached. It may do nothing, or ascend all the way to the top
2839 level.
2840 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07002841 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002842 if(uErr != QCBOR_SUCCESS) {
2843 goto Done;
2844 }
2845
Laurence Lundblade02625d42020-06-25 14:41:41 -07002846 /*
2847 This makes the next highest bounded level the current bounded
2848 level. If there is no next highest level, then no bounded mode is
2849 in effect.
2850 */
2851 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002852
Laurence Lundblade02625d42020-06-25 14:41:41 -07002853 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002854
2855Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002856 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002857 return uErr;
2858}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002859
Laurence Lundblade02625d42020-06-25 14:41:41 -07002860
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002861// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002862void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002863{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002864 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002865 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002866 return;
2867 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002868
Laurence Lundblade02625d42020-06-25 14:41:41 -07002869 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002870
Laurence Lundblade02625d42020-06-25 14:41:41 -07002871 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002872 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2873 goto Done;
2874 }
2875
Laurence Lundblade02625d42020-06-25 14:41:41 -07002876 /*
2877 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002878 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002879 from previous map search, then do a dummy search.
2880 */
2881 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002882 QCBORItem Dummy;
2883 Dummy.uLabelType = QCBOR_TYPE_NONE;
2884 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2885 if(uErr != QCBOR_SUCCESS) {
2886 goto Done;
2887 }
2888 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002889
Laurence Lundblade02625d42020-06-25 14:41:41 -07002890 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002891
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002892Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002893 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002894}
2895
2896
Laurence Lundblade1341c592020-04-11 14:19:05 -07002897void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002898{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002899 // TODO: check for map mode; test this
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002900 //pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->u.ma.uCountTotal;
2901 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->u.ma.uStartOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002902}
2903
2904
Laurence Lundblade1341c592020-04-11 14:19:05 -07002905
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002906static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002907 const QCBORItem *pItem,
2908 uint8_t uTagRequirement,
2909 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002910{
2911 if(pMe->uLastError != QCBOR_SUCCESS) {
2912 // Already in error state; do nothing.
2913 return pMe->uLastError;
2914 }
2915
2916 QCBORError uError = QCBOR_SUCCESS;
2917
2918 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2919 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2920 goto Done;;
2921 }
2922
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002923 const TagSpecification TagSpec = {uTagRequirement,
2924 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
2925 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
2926 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002927
2928 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2929 if(uError != QCBOR_SUCCESS) {
2930 goto Done;
2931 }
2932
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002933 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002934 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002935 so the increment in NestLevelAscender called by ExitBoundedLevel()
2936 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002937 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002938 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002939
2940 if(pBstr) {
2941 *pBstr = pItem->val.string;
2942 }
2943
2944 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002945
2946 // Need to move UIB input cursor to the right place
2947
2948 // Really this is a subtraction and an assignment; not much code
2949 // There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002950 // The bstr was just consumed so the cursor is at the next item after it
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002951
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002952 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002953
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002954 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
2955
2956 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002957
Laurence Lundblade02625d42020-06-25 14:41:41 -07002958 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
2959 uPreviousLength,
2960 uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002961Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002962 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002963
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002964 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002965}
2966
2967
Laurence Lundblade02625d42020-06-25 14:41:41 -07002968/*
2969 Public function, see header qcbor/qcbor_decode.h file
2970 */
2971void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002972 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002973 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002974{
2975 if(pMe->uLastError != QCBOR_SUCCESS) {
2976 // Already in error state; do nothing.
2977 return;
2978 }
2979
2980 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002981 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002982 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
2983 if(pMe->uLastError != QCBOR_SUCCESS) {
2984 return;
2985 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002986
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002987 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002988 &Item,
2989 uTagRequirement,
2990 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002991}
2992
2993
Laurence Lundblade02625d42020-06-25 14:41:41 -07002994/*
2995 Public function, see header qcbor/qcbor_decode.h file
2996 */
2997void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
2998 uint8_t uTagRequirement,
2999 int64_t nLabel,
3000 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003001{
3002 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003003 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003004
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003005 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003006}
3007
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003008
Laurence Lundblade02625d42020-06-25 14:41:41 -07003009/*
3010 Public function, see header qcbor/qcbor_decode.h file
3011 */
3012void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
3013 uint8_t uTagRequirement,
3014 const char *szLabel,
3015 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003016{
3017 QCBORItem Item;
3018 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3019
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003020 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003021}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003022
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003023
Laurence Lundblade02625d42020-06-25 14:41:41 -07003024/*
3025 Public function, see header qcbor/qcbor_decode.h file
3026 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003027void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003028{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003029 if(pMe->uLastError != QCBOR_SUCCESS) {
3030 // Already in error state; do nothing.
3031 return;
3032 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003033
Laurence Lundblade02625d42020-06-25 14:41:41 -07003034 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3035 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3036 return;
3037 }
3038
3039 /*
3040 Reset the length of the UsefulInputBuf to what it was before
3041 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003042 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003043 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3044 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003045
3046
Laurence Lundblade02625d42020-06-25 14:41:41 -07003047 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003048 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003049}
3050
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003051
Laurence Lundbladee6430642020-03-14 21:15:44 -07003052
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003053
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003054
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003055
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003056
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003057
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003058static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3059{
3060 switch(pItem->uDataType) {
3061 case QCBOR_TYPE_TRUE:
3062 *pBool = true;
3063 return QCBOR_SUCCESS;
3064 break;
3065
3066 case QCBOR_TYPE_FALSE:
3067 *pBool = false;
3068 return QCBOR_SUCCESS;
3069 break;
3070
3071 default:
3072 return QCBOR_ERR_UNEXPECTED_TYPE;
3073 break;
3074 }
3075}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003076
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003077/*
3078Public function, see header qcbor/qcbor_decode.h file
3079*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003080void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003081{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003082 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003083 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003084 return;
3085 }
3086
Laurence Lundbladec4537442020-04-14 18:53:22 -07003087 QCBORError nError;
3088 QCBORItem Item;
3089
3090 nError = QCBORDecode_GetNext(pMe, &Item);
3091 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003092 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003093 return;
3094 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003095 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003096}
3097
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003098/*
3099Public function, see header qcbor/qcbor_decode.h file
3100*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003101void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003102{
3103 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003104 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003105
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003106 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003107}
3108
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003109/*
3110Public function, see header qcbor/qcbor_decode.h file
3111*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003112void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3113{
3114 QCBORItem Item;
3115 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3116
3117 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3118}
3119
3120
3121
3122void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003123{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003124 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003125 // Already in error state, do nothing
3126 return;
3127 }
3128
3129 QCBORError nError;
3130 QCBORItem Item;
3131
3132 nError = QCBORDecode_GetNext(pMe, &Item);
3133 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003134 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003135 return;
3136 }
3137
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003138 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3139
3140 if(pMe->uLastError == QCBOR_SUCCESS) {
3141 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003142 }
3143}
3144
Laurence Lundbladec4537442020-04-14 18:53:22 -07003145
3146
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003147
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003148static QCBORError ConvertBigNum(uint8_t uTagRequirement,
3149 const QCBORItem *pItem,
3150 UsefulBufC *pValue,
3151 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003152{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003153 const TagSpecification TagSpec = {uTagRequirement,
3154 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3155 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3156 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003157
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003158 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
3159 if(uErr != QCBOR_SUCCESS) {
3160 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003161 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003162
3163 *pValue = pItem->val.string;
3164
3165 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3166 *pbIsNegative = false;
3167 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3168 *pbIsNegative = true;
3169 }
3170
3171 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003172}
3173
3174
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003175/**
3176 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003177 */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003178void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003179{
3180 if(pMe->uLastError != QCBOR_SUCCESS) {
3181 // Already in error state, do nothing
3182 return;
3183 }
3184
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003185 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003186 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3187 if(uError != QCBOR_SUCCESS) {
3188 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003189 return;
3190 }
3191
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003192 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003193}
3194
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003195/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003196Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003197*/
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003198void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003199{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003200 QCBORItem Item;
3201 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003202
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003203 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003204}
3205
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003206/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003207Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003208*/
3209void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
3210{
3211 QCBORItem Item;
3212 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3213
3214 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
3215}
3216
3217
3218
3219// Semi private
3220QCBORError FarfMIME(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsNot7Bit)
3221{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003222
3223
3224 const TagSpecification TagSpecText = {uTagRequirement,
3225 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3226 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3227 };
3228 const TagSpecification TagSpecBinary = {uTagRequirement,
3229 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3230 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3231 };
3232
3233
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003234 QCBORError uReturn;
3235
3236 if(CheckTagRequirement(TagSpecText, pItem->uDataType)) {
3237 *pMessage = pItem->val.string;
3238 if(pbIsNot7Bit != NULL) {
3239 *pbIsNot7Bit = false;
3240 }
3241 uReturn = QCBOR_SUCCESS;
3242 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType)) {
3243 *pMessage = pItem->val.string;
3244 if(pbIsNot7Bit != NULL) {
3245 *pbIsNot7Bit = true;
3246 }
3247 uReturn = QCBOR_SUCCESS;
3248
3249 } else {
3250 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3251 }
3252
3253 return uReturn;
3254}
3255
3256
3257
3258
3259
Laurence Lundbladec4537442020-04-14 18:53:22 -07003260
3261
3262
Laurence Lundbladee6430642020-03-14 21:15:44 -07003263
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003264typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003265
3266
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003267// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003268static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003269{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003270 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003271
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003272 if(uResult != 0) {
3273 /* This loop will run a maximum of 19 times because
3274 * UINT64_MAX < 10 ^^ 19. More than that will cause
3275 * exit with the overflow error
3276 */
3277 for(; nExponent > 0; nExponent--) {
3278 if(uResult > UINT64_MAX / 10) {
3279 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3280 }
3281 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003282 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003283
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003284 for(; nExponent < 0; nExponent++) {
3285 uResult = uResult / 10;
3286 if(uResult == 0) {
3287 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3288 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003289 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003290 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003291 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003292
3293 *puResult = uResult;
3294
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003295 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003296}
3297
3298
Laurence Lundbladee6430642020-03-14 21:15:44 -07003299/* Convert a decimal fraction to an int64_t without using
3300 floating point or math libraries. Most decimal fractions
3301 will not fit in an int64_t and this will error out with
3302 under or overflow
3303 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003304static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003305{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003306 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003307
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003308 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003309
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003310 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003311 * INT64_MAX < 2^31. More than that will cause
3312 * exist with the overflow error
3313 */
3314 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003315 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003316 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003317 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003318 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003319 nExponent--;
3320 }
3321
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003322 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003323 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003324 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3325 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003326 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003327 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003328 }
3329
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003330 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003331
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003332 return QCBOR_SUCCESS;
3333}
3334
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003335/*
3336 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3337 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003338static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3339{
3340 uint64_t uResult;
3341
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003342 // Take the absolute value of the mantissa and convert to unsigned.
3343 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003344 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3345
3346 // Do the exponentiation of the positive mantissa
3347 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3348 if(uReturn) {
3349 return uReturn;
3350 }
3351
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003352
Laurence Lundblade983500d2020-05-14 11:49:34 -07003353 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3354 of INT64_MIN. This assumes two's compliment representation where
3355 INT64_MIN is one increment farther from 0 than INT64_MAX.
3356 Trying to write -INT64_MIN doesn't work to get this because the
3357 compiler tries to work with an int64_t which can't represent
3358 -INT64_MIN.
3359 */
3360 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3361
3362 // Error out if too large
3363 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003364 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3365 }
3366
3367 // Casts are safe because of checks above
3368 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3369
3370 return QCBOR_SUCCESS;
3371}
3372
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003373/*
3374 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3375 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003376static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3377{
3378 if(nMantissa < 0) {
3379 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3380 }
3381
3382 // Cast to unsigned is OK because of check for negative
3383 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3384 // Exponentiation is straight forward
3385 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3386}
3387
3388
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003389#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003390
3391
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003392static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003393{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003394 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003395
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003396 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003397 const uint8_t *pByte = BigNum.ptr;
3398 size_t uLen = BigNum.len;
3399 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003400 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003401 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003402 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003403 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003404 }
3405
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003406 *pResult = uResult;
3407 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003408}
3409
Laurence Lundblade887add82020-05-17 05:50:34 -07003410static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003411{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003412 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003413}
3414
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003415static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003416{
3417 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003418 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3419 if(uError) {
3420 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003421 }
3422 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3423 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003424 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003425}
3426
3427
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003428static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003429{
3430 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003431 /* negaative int furthest from zero is INT64_MIN
3432 which is expressed as -INT64_MAX-1. The value of
3433 a negative bignum is -n-1, one further from zero
3434 than the positive bignum */
3435
3436 /* say INT64_MIN is -2; then INT64_MAX is 1.
3437 Then -n-1 <= INT64_MIN.
3438 Then -n -1 <= -INT64_MAX - 1
3439 THen n <= INT64_MAX. */
3440 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003441 if(uError) {
3442 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003443 }
3444 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003445 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003446 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003447 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003448 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003449}
3450
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003451#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003452
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003453
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003454/*
3455Convert a integers and floats to an int64_t.
3456
3457\param[in] uOptions Bit mask list of conversion options.
3458
3459\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3460
3461\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3462
3463\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3464
3465*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003466static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3467{
3468 switch(pItem->uDataType) {
3469 // TODO: float when ifdefs are set
3470 case QCBOR_TYPE_DOUBLE:
3471 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3472 // TODO: what about under/overflow here?
3473 // Invokes the floating-point HW and/or compiler-added libraries
3474 feclearexcept(FE_ALL_EXCEPT);
3475 *pnValue = llround(pItem->val.dfnum);
3476 if(fetestexcept(FE_INVALID)) {
3477 // TODO: better error code
3478 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3479 }
3480 } else {
3481 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3482 }
3483 break;
3484
3485 case QCBOR_TYPE_INT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003486 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003487 *pnValue = pItem->val.int64;
3488 } else {
3489 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3490 }
3491 break;
3492
3493 case QCBOR_TYPE_UINT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003494 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003495 if(pItem->val.uint64 < INT64_MAX) {
3496 *pnValue = pItem->val.int64;
3497 } else {
3498 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3499 }
3500 } else {
3501 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3502 }
3503 break;
3504
3505 default:
3506 return QCBOR_ERR_UNEXPECTED_TYPE;
3507 }
3508 return QCBOR_SUCCESS;
3509}
3510
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003511
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003512void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
3513 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003514 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003515 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003516{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003517 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003518 return;
3519 }
3520
Laurence Lundbladee6430642020-03-14 21:15:44 -07003521 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003522 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3523 if(uError) {
3524 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003525 return;
3526 }
3527
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003528 if(pItem) {
3529 *pItem = Item;
3530 }
3531
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003532 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003533}
3534
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003535
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003536void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3537 int64_t nLabel,
3538 uint32_t uOptions,
3539 int64_t *pnValue,
3540 QCBORItem *pItem)
3541{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003542 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003543 if(pMe->uLastError != QCBOR_SUCCESS) {
3544 return;
3545 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003546
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003547 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003548}
3549
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003550
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003551void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3552 const char * szLabel,
3553 uint32_t uOptions,
3554 int64_t *pnValue,
3555 QCBORItem *pItem)
3556{
3557 if(pMe->uLastError != QCBOR_SUCCESS) {
3558 return;
3559 }
3560
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003561 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003562 if(pMe->uLastError != QCBOR_SUCCESS) {
3563 return;
3564 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003565
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003566 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003567}
3568
3569
3570
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003571/*
3572 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003573
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003574 \param[in] uOptions Bit mask list of conversion options.
3575
3576 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3577
3578 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3579
3580 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3581
3582 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003583static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3584{
3585 QCBORError uErr;
3586
3587 switch(pItem->uDataType) {
3588
3589 case QCBOR_TYPE_POSBIGNUM:
3590 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3591 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003592 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003593 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003594 }
3595 break;
3596
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003597 case QCBOR_TYPE_NEGBIGNUM:
3598 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3599 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003600 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003601 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003602 }
3603 break;
3604
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003605#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3606 case QCBOR_TYPE_DECIMAL_FRACTION:
3607 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3608 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3609 pItem->val.expAndMantissa.nExponent,
3610 pnValue,
3611 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003612 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003613 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3614 }
3615 break;
3616
3617 case QCBOR_TYPE_BIGFLOAT:
3618 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3619 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3620 pItem->val.expAndMantissa.nExponent,
3621 pnValue,
3622 Exponentitate2);
3623 } else {
3624 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3625 }
3626 break;
3627
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003628 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3629 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3630 int64_t nMantissa;
3631 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3632 if(uErr) {
3633 return uErr;
3634 }
3635 return ExponentiateNN(nMantissa,
3636 pItem->val.expAndMantissa.nExponent,
3637 pnValue,
3638 Exponentitate10);
3639 } else {
3640 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3641 }
3642 break;
3643
3644 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3645 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3646 int64_t nMantissa;
3647 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3648 if(uErr) {
3649 return uErr;
3650 }
3651 return ExponentiateNN(nMantissa,
3652 pItem->val.expAndMantissa.nExponent,
3653 pnValue,
3654 Exponentitate10);
3655 } else {
3656 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3657 }
3658 break;
3659
3660 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3661 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3662 int64_t nMantissa;
3663 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3664 if(uErr) {
3665 return uErr;
3666 }
3667 return ExponentiateNN(nMantissa,
3668 pItem->val.expAndMantissa.nExponent,
3669 pnValue,
3670 Exponentitate2);
3671 } else {
3672 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3673 }
3674 break;
3675
3676 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3677 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3678 int64_t nMantissa;
3679 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3680 if(uErr) {
3681 return uErr;
3682 }
3683 return ExponentiateNN(nMantissa,
3684 pItem->val.expAndMantissa.nExponent,
3685 pnValue,
3686 Exponentitate2);
3687 } else {
3688 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003689 }
3690 break;
3691
Laurence Lundbladec4537442020-04-14 18:53:22 -07003692 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003693 return QCBOR_ERR_UNEXPECTED_TYPE;
3694#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07003695 }
3696}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003697
3698
Laurence Lundbladec4537442020-04-14 18:53:22 -07003699/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003700 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003701 */
3702void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003703{
3704 QCBORItem Item;
3705
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003706 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003707
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003708 if(pMe->uLastError == QCBOR_SUCCESS) {
3709 // The above conversion succeeded
3710 return;
3711 }
3712
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003713 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003714 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003715 return;
3716 }
3717
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003718 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003719}
3720
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003721
3722/*
3723Public function, see header qcbor/qcbor_decode.h file
3724*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003725void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
3726{
3727 QCBORItem Item;
3728
3729 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
3730
3731 if(pMe->uLastError == QCBOR_SUCCESS) {
3732 // The above conversion succeeded
3733 return;
3734 }
3735
3736 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3737 // The above conversion failed in a way that code below can't correct
3738 return;
3739 }
3740
3741 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3742}
3743
3744
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003745/*
3746Public function, see header qcbor/qcbor_decode.h file
3747*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003748void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3749{
3750 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003751 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3752
3753 if(pMe->uLastError == QCBOR_SUCCESS) {
3754 // The above conversion succeeded
3755 return;
3756 }
3757
3758 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3759 // The above conversion failed in a way that code below can't correct
3760 return;
3761 }
3762
3763 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3764}
3765
3766
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003767static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3768{
3769 switch(pItem->uDataType) {
3770 // TODO: type flaot
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07003771 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003772 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3773 feclearexcept(FE_ALL_EXCEPT);
3774 double dRounded = round(pItem->val.dfnum);
3775 // TODO: over/underflow
3776 if(fetestexcept(FE_INVALID)) {
3777 // TODO: better error code
3778 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3779 } else if(isnan(dRounded)) {
3780 // TODO: better error code
3781 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3782 } else if(dRounded >= 0) {
3783 *puValue = (uint64_t)dRounded;
3784 } else {
3785 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3786 }
3787 } else {
3788 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3789 }
3790 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003791
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003792 case QCBOR_TYPE_INT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003793 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003794 if(pItem->val.int64 >= 0) {
3795 *puValue = (uint64_t)pItem->val.int64;
3796 } else {
3797 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3798 }
3799 } else {
3800 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3801 }
3802 break;
3803
3804 case QCBOR_TYPE_UINT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003805 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003806 *puValue = pItem->val.uint64;
3807 } else {
3808 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3809 }
3810 break;
3811
3812 default:
3813 return QCBOR_ERR_UNEXPECTED_TYPE;
3814 }
3815 return QCBOR_SUCCESS;
3816}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003817
3818
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003819void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3820 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003821 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003822 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003823{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003824 if(pMe->uLastError != QCBOR_SUCCESS) {
3825 return;
3826 }
3827
Laurence Lundbladec4537442020-04-14 18:53:22 -07003828 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003829
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003830 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3831 if(uError) {
3832 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003833 return;
3834 }
3835
Laurence Lundbladea826c502020-05-10 21:07:00 -07003836 if(pItem) {
3837 *pItem = Item;
3838 }
3839
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003840 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003841}
3842
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003843
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003844void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3845{
3846 int64_t uValue;
3847 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, &uValue, pItem);
3848 if(pMe->uLastError != QCBOR_SUCCESS) {
3849 return;
3850 }
3851
3852 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3853 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3854 }
3855}
3856
3857void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3858{
3859 int64_t uValue;
3860 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, &uValue, pItem);
3861 if(pMe->uLastError != QCBOR_SUCCESS) {
3862 return;
3863 }
3864
3865 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3866 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3867 }
3868}
3869
3870void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3871{
3872 int64_t uValue;
3873 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, &uValue, pItem);
3874 if(pMe->uLastError != QCBOR_SUCCESS) {
3875 return;
3876 }
3877
3878 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3879 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3880 }
3881}
3882
3883
3884
3885
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003886void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3887 int64_t nLabel,
3888 uint32_t uOptions,
3889 uint64_t *puValue,
3890 QCBORItem *pItem)
3891{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003892 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003893 if(pMe->uLastError != QCBOR_SUCCESS) {
3894 return;
3895 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003896
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003897 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uOptions, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003898}
3899
3900
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003901void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003902 const char * szLabel,
3903 uint32_t uOptions,
3904 uint64_t *puValue,
3905 QCBORItem *pItem)
3906{
3907 if(pMe->uLastError != QCBOR_SUCCESS) {
3908 return;
3909 }
3910
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003911 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003912 if(pMe->uLastError != QCBOR_SUCCESS) {
3913 return;
3914 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003915
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003916 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uOptions, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003917}
3918
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003919/*
3920 Public function, see header qcbor/qcbor_decode.h file
3921*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003922static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3923{
3924 QCBORError uErr;
3925
3926 switch(pItem->uDataType) {
3927
3928 case QCBOR_TYPE_POSBIGNUM:
3929 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3930 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3931 } else {
3932 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3933 }
3934 break;
3935
3936 case QCBOR_TYPE_NEGBIGNUM:
3937 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3938 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3939 } else {
3940 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3941 }
3942 break;
3943
3944#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3945
3946 case QCBOR_TYPE_DECIMAL_FRACTION:
3947 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3948 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3949 pItem->val.expAndMantissa.nExponent,
3950 puValue,
3951 Exponentitate10);
3952 } else {
3953 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3954 }
3955 break;
3956
3957 case QCBOR_TYPE_BIGFLOAT:
3958 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3959 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3960 pItem->val.expAndMantissa.nExponent,
3961 puValue,
3962 Exponentitate2);
3963 } else {
3964 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3965 }
3966 break;
3967
3968 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3969 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3970 // TODO: Would be better to convert to unsigned
3971 int64_t nMantissa;
3972 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3973 if(uErr != QCBOR_SUCCESS) {
3974 return uErr;
3975 }
3976 return ExponentitateNU(nMantissa,
3977 pItem->val.expAndMantissa.nExponent,
3978 puValue,
3979 Exponentitate10);
3980 } else {
3981 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3982 }
3983 break;
3984
3985 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3986 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3987 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3988 } else {
3989 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3990 }
3991 break;
3992
3993 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3994 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3995 // TODO: Would be better to convert to unsigned
3996 int64_t nMantissa;
3997 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3998 if(uErr != QCBOR_SUCCESS) {
3999 return uErr;
4000 }
4001 return ExponentitateNU(nMantissa,
4002 pItem->val.expAndMantissa.nExponent,
4003 puValue,
4004 Exponentitate2);
4005 } else {
4006 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4007 }
4008 break;
4009
4010 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4011 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4012 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4013 } else {
4014 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4015 }
4016 break;
4017#endif
4018 default:
4019 return QCBOR_ERR_UNEXPECTED_TYPE;
4020 }
4021}
4022
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004023/*
4024 Public function, see header qcbor/qcbor_decode.h file
4025*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004026void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004027{
4028 QCBORItem Item;
4029
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004030 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004031
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004032 if(pMe->uLastError == QCBOR_SUCCESS) {
4033 // The above conversion succeeded
4034 return;
4035 }
4036
4037 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4038 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004039 return;
4040 }
4041
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004042 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004043}
4044
Laurence Lundbladec4537442020-04-14 18:53:22 -07004045
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004046/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004047 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004048*/
4049void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
4050{
4051 QCBORItem Item;
4052
4053 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
4054
4055 if(pMe->uLastError == QCBOR_SUCCESS) {
4056 // The above conversion succeeded
4057 return;
4058 }
4059
4060 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4061 // The above conversion failed in a way that code below can't correct
4062 return;
4063 }
4064
4065 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4066}
4067
4068
4069/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004070 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004071*/
4072void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
4073{
4074 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004075 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004076
4077 if(pMe->uLastError == QCBOR_SUCCESS) {
4078 // The above conversion succeeded
4079 return;
4080 }
4081
4082 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4083 // The above conversion failed in a way that code below can't correct
4084 return;
4085 }
4086
4087 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4088}
4089
4090
4091static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
4092{
4093 switch(pItem->uDataType) {
4094 // TODO: float when ifdefs are set
4095 case QCBOR_TYPE_DOUBLE:
4096 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4097 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4098 *pdValue = pItem->val.dfnum;
4099 } else {
4100 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4101 }
4102 }
4103 break;
4104
4105 case QCBOR_TYPE_INT64:
4106 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
4107 // TODO: how does this work?
4108 *pdValue = (double)pItem->val.int64;
4109
4110 } else {
4111 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4112 }
4113 break;
4114
4115 case QCBOR_TYPE_UINT64:
4116 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
4117 *pdValue = (double)pItem->val.uint64;
4118 } else {
4119 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4120 }
4121 break;
4122
4123 default:
4124 return QCBOR_ERR_UNEXPECTED_TYPE;
4125 }
4126
4127 return QCBOR_SUCCESS;
4128}
4129
4130
4131
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004132void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
4133 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004134 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004135 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004136{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004137 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004138 return;
4139 }
4140
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004141 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004142
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004143 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004144 if(uError) {
4145 pMe->uLastError = (uint8_t)uError;
4146 return;
4147 }
4148
4149 if(pItem) {
4150 *pItem = Item;
4151 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004152
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004153 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004154}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004155
Laurence Lundbladec4537442020-04-14 18:53:22 -07004156
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004157void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4158 int64_t nLabel,
4159 uint32_t uOptions,
4160 double *pdValue,
4161 QCBORItem *pItem)
4162{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004163 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004164 if(pMe->uLastError != QCBOR_SUCCESS) {
4165 return;
4166 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004167
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004168 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uOptions, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004169}
4170
4171void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4172 const char * szLabel,
4173 uint32_t uOptions,
4174 double *pdValue,
4175 QCBORItem *pItem)
4176{
4177 if(pMe->uLastError != QCBOR_SUCCESS) {
4178 return;
4179 }
4180
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004181 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004182 if(pMe->uLastError != QCBOR_SUCCESS) {
4183 return;
4184 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004185
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004186 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uOptions, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004187}
4188
4189
4190
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004191static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4192{
4193 double dResult;
4194
4195 dResult = 0.0;
4196 const uint8_t *pByte = BigNum.ptr;
4197 size_t uLen = BigNum.len;
4198 /* This will overflow and become the float value INFINITY if the number
4199 is too large to fit. No error will be logged.
4200 TODO: should an error be logged? */
4201 while(uLen--) {
4202 dResult = (dResult * 256.0) + (double)*pByte++;
4203 }
4204
4205 return dResult;
4206}
4207
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004208static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004209{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004210 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004211 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4212
4213 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004214 switch(pItem->uDataType) {
4215 // TODO: type float
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004216
4217#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004218 case QCBOR_TYPE_DECIMAL_FRACTION:
4219 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4220 // TODO: rounding and overflow errors
4221 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4222 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4223 } else {
4224 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4225 }
4226 break;
4227
4228 case QCBOR_TYPE_BIGFLOAT:
4229 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
4230 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4231 exp2((double)pItem->val.expAndMantissa.nExponent);
4232 } else {
4233 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4234 }
4235 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004236#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004237
4238 case QCBOR_TYPE_POSBIGNUM:
4239 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
4240 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4241 } else {
4242 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4243 }
4244 break;
4245
4246 case QCBOR_TYPE_NEGBIGNUM:
4247 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004248 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004249 } else {
4250 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4251 }
4252 break;
4253
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004254#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004255 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4256 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4257 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4258 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4259 } else {
4260 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4261 }
4262 break;
4263
4264 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4265 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4266 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4267 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4268 } else {
4269 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4270 }
4271 break;
4272
4273 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4274 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
4275 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4276 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4277 } else {
4278 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4279 }
4280 break;
4281
4282 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4283 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004284 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004285 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4286 } else {
4287 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4288 }
4289 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004290#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4291
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004292
4293 default:
4294 return QCBOR_ERR_UNEXPECTED_TYPE;
4295 }
4296
4297 return QCBOR_SUCCESS;
4298}
4299
4300
4301/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004302 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004303*/
4304void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
4305{
4306
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004307 QCBORItem Item;
4308
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004309 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004310
4311 if(pMe->uLastError == QCBOR_SUCCESS) {
4312 // The above conversion succeeded
4313 return;
4314 }
4315
4316 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4317 // The above conversion failed in a way that code below can't correct
4318 return;
4319 }
4320
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004321 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004322}
4323
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004324
4325/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004326 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004327*/
4328void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
4329{
4330 QCBORItem Item;
4331
4332 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
4333
4334 if(pMe->uLastError == QCBOR_SUCCESS) {
4335 // The above conversion succeeded
4336 return;
4337 }
4338
4339 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4340 // The above conversion failed in a way that code below can't correct
4341 return;
4342 }
4343
4344 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4345}
4346
4347
4348/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004349 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004350*/
4351void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
4352{
4353 QCBORItem Item;
4354 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
4355
4356 if(pMe->uLastError == QCBOR_SUCCESS) {
4357 // The above conversion succeeded
4358 return;
4359 }
4360
4361 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4362 // The above conversion failed in a way that code below can't correct
4363 return;
4364 }
4365
4366 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4367}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004368
4369
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004370#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004371static void ProcessDecimalFraction(QCBORDecodeContext *pMe,
4372 uint8_t uTagRequirement,
4373 QCBORItem *pItem,
4374 int64_t *pnMantissa,
4375 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004376{
4377 QCBORError uErr;
4378
4379 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004380
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004381 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4382 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4383 return;
4384 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004385 /* The decimal fraction was untagged so it shows up as an
4386 array at this point. We are called to interpret it
4387 as a decimal fraction, so do protocol decoding. If
4388 it was tagged, iw would shouw up here with the
4389 QCBOR_TYPE_DECIMAL_FRACTION or such. */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004390 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4391 if(uErr != QCBOR_SUCCESS) {
4392 pMe->uLastError = (uint8_t)uErr;
4393 return;
4394 }
4395 }
4396
4397 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4398 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4399 return;
4400 }
4401
4402 switch (pItem->uDataType) {
4403
4404 case QCBOR_TYPE_DECIMAL_FRACTION:
4405 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4406 *pnExponent = pItem->val.expAndMantissa.nExponent;
4407 break;
4408
4409 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4410 *pnExponent = pItem->val.expAndMantissa.nExponent;
4411
4412 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4413 if(uErr != QCBOR_SUCCESS) {
4414 pMe->uLastError = (uint8_t)uErr;
4415 }
4416 break;
4417
4418 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4419 *pnExponent = pItem->val.expAndMantissa.nExponent;
4420
4421 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4422 if(uErr != QCBOR_SUCCESS) {
4423 pMe->uLastError = (uint8_t)uErr;
4424 }
4425 break;
4426
4427 default:
4428 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4429 }
4430}
4431
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004432
4433void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
4434 uint8_t uTagRequirement,
4435 int64_t *pnMantissa,
4436 int64_t *pnExponent)
4437{
4438 if(pMe->uLastError != QCBOR_SUCCESS) {
4439 return;
4440 }
4441
4442 QCBORItem Item;
4443 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4444 if(uError) {
4445 pMe->uLastError = (uint8_t)uError;
4446 return;
4447 }
4448
4449 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4450}
4451
4452
4453void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004454 uint8_t uTagRequirement,
4455 int64_t nLabel,
4456 int64_t *pnMantissa,
4457 int64_t *pnExponent)
4458{
4459 QCBORItem Item;
4460
4461 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004462 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004463}
4464
4465
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004466void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
4467 uint8_t uTagRequirement,
4468 const char *szLabel,
4469 int64_t *pnMantissa,
4470 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004471{
4472 QCBORItem Item;
4473
4474 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4475
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004476 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004477}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004478#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004479
4480
4481UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4482{
4483 while(uInt & 0xff0000000000UL) {
4484 uInt = uInt << 8;
4485 };
4486
4487 UsefulOutBuf UOB;
4488
4489 UsefulOutBuf_Init(&UOB, Buffer);
4490
4491 while(uInt) {
4492 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56));
4493 uInt = uInt << 8;
4494 }
4495
4496 return UsefulOutBuf_OutUBuf(&UOB);
4497}
4498
4499
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004500#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4501
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004502static void ProcessDecimalFractionBig(QCBORDecodeContext *pMe,
4503 uint8_t uTagRequirement,
4504 QCBORItem *pItem,
4505 UsefulBuf BufferForMantissa,
4506 UsefulBufC *pMantissa,
4507 bool *pbIsNegative,
4508 int64_t *pnExponent)
4509{
4510
4511 const TagSpecification TagSpec = {uTagRequirement,
4512 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4513 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4514 };
4515
4516 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
4517 if(uErr != QCBOR_SUCCESS) {
4518 pMe->uLastError = (uint8_t)uErr;
4519 return;
4520 }
4521
4522 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
4523 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4524 if(uErr != QCBOR_SUCCESS) {
4525 pMe->uLastError = (uint8_t)uErr;
4526 return;
4527 }
4528 }
4529
4530 uint64_t uMantissa;
4531
4532 switch (pItem->uDataType) {
4533
4534 case QCBOR_TYPE_DECIMAL_FRACTION:
4535 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
4536 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
4537 *pbIsNegative = false;
4538 } else {
4539 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
4540 *pbIsNegative = true;
4541 }
4542 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
4543 *pnExponent = pItem->val.expAndMantissa.nExponent;
4544 break;
4545
4546 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4547 *pnExponent = pItem->val.expAndMantissa.nExponent;
4548 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4549 *pbIsNegative = false;
4550 break;
4551
4552 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4553 *pnExponent = pItem->val.expAndMantissa.nExponent;
4554 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4555 *pbIsNegative = true;
4556 break;
4557
4558 default:
4559 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4560 }
4561}
4562
4563
4564void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
4565 uint8_t uTagRequirement,
4566 UsefulBuf MantissaBuffer,
4567 UsefulBufC *pMantissa,
4568 bool *pbMantissaIsNegative,
4569 int64_t *pnExponent)
4570{
4571
4572 if(pMe->uLastError != QCBOR_SUCCESS) {
4573 return;
4574 }
4575
4576 QCBORItem Item;
4577 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4578 if(uError) {
4579 pMe->uLastError = (uint8_t)uError;
4580 return;
4581 }
4582
4583 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
4584
4585}
4586
4587void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
4588 uint8_t uTagRequirement,
4589 int64_t nLabel,
4590 UsefulBuf BufferForMantissa,
4591 UsefulBufC *pMantissa,
4592 bool *pbIsNegative,
4593 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004594{
4595 QCBORItem Item;
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004596
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004597 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004598 if(pMe->uLastError != QCBOR_SUCCESS) {
4599 return;
4600 }
4601
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004602 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
4603}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004604
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004605
4606void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
4607 uint8_t uTagRequirement,
4608 const char *szLabel,
4609 UsefulBuf BufferForMantissa,
4610 UsefulBufC *pMantissa,
4611 bool *pbIsNegative,
4612 int64_t *pnExponent)
4613{
4614 QCBORItem Item;
4615
4616 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4617 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004618 return;
4619 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004620
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004621 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004622}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004623
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004624#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004625
4626/*
4627
4628 TODO: do something with this text
4629 The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...)
4630 formed by intermediate nodes (arrays and maps). The cursor for the traversal
4631 is the byte offset in the encoded input and a leaf counter for definite
4632 length maps and arrays. Indefinite length maps and arrays are handled
4633 by look ahead for the break.
4634
4635 The view presented to the caller has tags, labels and the chunks of
4636 indefinite length strings aggregated into one decorated data item.
4637
4638 The caller understands the nesting level in pre-order traversal by
4639 the fact that a data item that is a map or array is presented to
4640 the caller when it is first encountered in the pre-order traversal and that all data items are presented with its nesting level
4641 and the nesting level of the next item.
4642
4643 The caller traverse maps and arrays in a special mode that often more convenient
4644 that tracking by nesting level. When an array or map is expected or encountered
4645 the EnterMap or EnteryArray can be called.
4646
4647 When entering a map or array like this, the cursor points to the first
4648 item in the map or array. When exiting, it points to the item after
4649 the map or array, regardless of whether the items in the map or array were
4650 all traversed.
4651
4652 When in a map or array, the cursor functions as normal, but traversal
4653 cannot go past the end of the map or array that was entered. If this
4654 is attempted the QCBOR_ERR_NO_MORE_ITEMS error is returned. To
4655 go past the end of the map or array ExitMap() or ExitArray() must
4656 be called. It can be called any time regardless of the position
4657 of the cursor.
4658
4659 When a map is entered, a special function allows fetching data items
4660 by label. This call will traversal the whole map looking for the
4661 labeled item. The whole map is traversed so as to detect duplicates.
4662 This type of fetching items does not affect the normal traversal
4663 cursor.
4664
4665
4666 When a data item is presented to the caller, the nesting level of the data
4667 item is presented along with the nesting level of the item that would be
4668 next consumed.
4669 */