blob: 549bbbc84f59a6e2ed8d72253a96b62470fe2915 [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 Lundblade2c1faf92020-06-26 22:43:56 -0700477 printf("---%s--%d/%d--\narrow is current bounded level\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700478 szName,
479 (uint32_t)pBuf->cursor,
480 (uint32_t)pBuf->UB.len);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700481
482 printf("Level Type Count Offsets \n");
Laurence Lundblade02625d42020-06-25 14:41:41 -0700483 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700484 if(&(pNesting->pLevels[i]) > pNesting->pCurrent) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700485 break;
486 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700487
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700488 printf("%2s %2d %s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700489 pNesting->pCurrentBounded == &(pNesting->pLevels[i]) ? "->": " ",
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700490 i,
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700491 TypeStr(pNesting->pLevels[i].uLevelType));
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700492
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700493 if(pNesting->pLevels[i].uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700494 printf(" %5d %5d",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700495 pNesting->pLevels[i].u.bs.uEndOfBstr,
496 pNesting->pLevels[i].u.bs.uPreviousEndOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700497
498 } else {
499 printf("%10.10s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700500 CountString(pNesting->pLevels[i].u.ma.uCountCursor,
501 pNesting->pLevels[i].u.ma.uCountTotal));
502 if(pNesting->pLevels[i].u.ma.uStartOffset != UINT32_MAX) {
503 printf("Bounded start: %u",pNesting->pLevels[i].u.ma.uStartOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700504 }
505 }
506
507 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700508 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700509 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700510}
511
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700512
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700513
Laurence Lundbladeee851742020-01-08 08:37:05 -0800514/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800515 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
516
517 The following four functions are pretty wrappers for invocation of
518 the string allocator supplied by the caller.
519
Laurence Lundbladeee851742020-01-08 08:37:05 -0800520 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800521
Laurence Lundbladeee851742020-01-08 08:37:05 -0800522static inline void
523StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800524{
525 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
526}
527
Laurence Lundbladeee851742020-01-08 08:37:05 -0800528// StringAllocator_Reallocate called with pMem NULL is
529// equal to StringAllocator_Allocate()
530static inline UsefulBuf
531StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
532 void *pMem,
533 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800534{
535 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
536}
537
Laurence Lundbladeee851742020-01-08 08:37:05 -0800538static inline UsefulBuf
539StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800540{
541 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
542}
543
Laurence Lundbladeee851742020-01-08 08:37:05 -0800544static inline void
545StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800546{
547 if(pMe->pfAllocator) {
548 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
549 }
550}
551
552
553
Laurence Lundbladeee851742020-01-08 08:37:05 -0800554/*===========================================================================
555 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700556
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800557 See qcbor/qcbor_decode.h for definition of the object
558 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800559 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700560/*
561 Public function, see header file
562 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800563void QCBORDecode_Init(QCBORDecodeContext *me,
564 UsefulBufC EncodedCBOR,
565 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700566{
567 memset(me, 0, sizeof(QCBORDecodeContext));
568 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800569 // Don't bother with error check on decode mode. If a bad value is
570 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700571 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700572 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700573 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700574 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700575 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700576}
577
578
579/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700580 Public function, see header file
581 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800582void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
583 QCBORStringAllocate pfAllocateFunction,
584 void *pAllocateContext,
585 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700586{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800587 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
588 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
589 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700590}
591
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800592
593/*
594 Public function, see header file
595 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700596void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800597 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700598{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700599 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700600 (void)pMe;
601 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700602}
603
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700604
605/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800606 This decodes the fundamental part of a CBOR data item, the type and
607 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800608
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700609 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800610
Laurence Lundbladeee851742020-01-08 08:37:05 -0800611 This does the network->host byte order conversion. The conversion
612 here also results in the conversion for floats in addition to that
613 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800614
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700615 This returns:
616 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800617
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800618 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800619 tags and floats and length for strings and arrays
620
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800621 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800622 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800623
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800624 The int type is preferred to uint8_t for some variables as this
625 avoids integer promotions, can reduce code size and makes
626 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700627 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800628inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
629 int *pnMajorType,
630 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800631 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700632{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700633 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800634
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700635 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800636 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800637
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700638 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800639 const int nTmpMajorType = nInitialByte >> 5;
640 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800641
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800642 // Where the number or argument accumulates
643 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800644
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800645 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700646 // Need to get 1,2,4 or 8 additional argument bytes. Map
647 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800648 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800649
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800650 // Loop getting all the bytes in the argument
651 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800652 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800653 // This shift and add gives the endian conversion
654 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
655 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800656 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800657 // The reserved and thus-far unused additional info values
658 nReturn = QCBOR_ERR_UNSUPPORTED;
659 goto Done;
660 } else {
661 // Less than 24, additional info is argument or 31, an indefinite length
662 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800663 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700664 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800665
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700666 if(UsefulInputBuf_GetError(pUInBuf)) {
667 nReturn = QCBOR_ERR_HIT_END;
668 goto Done;
669 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800670
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700671 // All successful if we got here.
672 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800673 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800674 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800675 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800676
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700677Done:
678 return nReturn;
679}
680
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800681
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700682/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800683 CBOR doesn't explicitly specify two's compliment for integers but all
684 CPUs use it these days and the test vectors in the RFC are so. All
685 integers in the CBOR structure are positive and the major type
686 indicates positive or negative. CBOR can express positive integers
687 up to 2^x - 1 where x is the number of bits and negative integers
688 down to 2^x. Note that negative numbers can be one more away from
689 zero than positive. Stdint, as far as I can tell, uses two's
690 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800691
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700692 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800693 used carefully here, and in particular why it isn't used in the interface.
694 Also see
695 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
696
697 Int is used for values that need less than 16-bits and would be subject
698 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700699 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800700inline static QCBORError
701DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700702{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700703 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800704
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700705 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
706 if (uNumber <= INT64_MAX) {
707 pDecodedItem->val.int64 = (int64_t)uNumber;
708 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800709
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700710 } else {
711 pDecodedItem->val.uint64 = uNumber;
712 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800713
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700714 }
715 } else {
716 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800717 // CBOR's representation of negative numbers lines up with the
718 // two-compliment representation. A negative integer has one
719 // more in range than a positive integer. INT64_MIN is
720 // equal to (-INT64_MAX) - 1.
721 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800723
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724 } else {
725 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000726 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700727 nReturn = QCBOR_ERR_INT_OVERFLOW;
728 }
729 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800730
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700731 return nReturn;
732}
733
734// Make sure #define value line up as DecodeSimple counts on this.
735#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
736#error QCBOR_TYPE_FALSE macro value wrong
737#endif
738
739#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
740#error QCBOR_TYPE_TRUE macro value wrong
741#endif
742
743#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
744#error QCBOR_TYPE_NULL macro value wrong
745#endif
746
747#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
748#error QCBOR_TYPE_UNDEF macro value wrong
749#endif
750
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700751#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
752#error QCBOR_TYPE_BREAK macro value wrong
753#endif
754
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700755#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
756#error QCBOR_TYPE_DOUBLE macro value wrong
757#endif
758
759#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
760#error QCBOR_TYPE_FLOAT macro value wrong
761#endif
762
763/*
764 Decode true, false, floats, break...
765 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800766inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800767DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700768{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700769 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800770
Laurence Lundbladeee851742020-01-08 08:37:05 -0800771 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800772 // above make sure uAdditionalInfo values line up with uDataType values.
773 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
774 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800775
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800776 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800777 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
778 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800779
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700780 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700781 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
782 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700783 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700784 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700785 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
786 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700787 break;
788 case DOUBLE_PREC_FLOAT:
789 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700790 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700791 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800792
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700793 case CBOR_SIMPLEV_FALSE: // 20
794 case CBOR_SIMPLEV_TRUE: // 21
795 case CBOR_SIMPLEV_NULL: // 22
796 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700797 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700798 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800799
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700800 case CBOR_SIMPLEV_ONEBYTE: // 24
801 if(uNumber <= CBOR_SIMPLE_BREAK) {
802 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700803 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700804 goto Done;
805 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800806 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700807 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800808
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700809 default: // 0-19
810 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800811 /*
812 DecodeTypeAndNumber will make uNumber equal to
813 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
814 safe because the 2, 4 and 8 byte lengths of uNumber are in
815 the double/float cases above
816 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700817 pDecodedItem->val.uSimple = (uint8_t)uNumber;
818 break;
819 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800820
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700821Done:
822 return nReturn;
823}
824
825
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700826/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530827 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700828 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800829inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
830 int nMajorType,
831 uint64_t uStrLen,
832 UsefulInputBuf *pUInBuf,
833 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700834{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700835 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800836
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800837 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
838 // This check makes the casts to size_t below safe.
839
840 // 4 bytes less than the largest sizeof() so this can be tested by
841 // putting a SIZE_MAX length in the CBOR test input (no one will
842 // care the limit on strings is 4 bytes shorter).
843 if(uStrLen > SIZE_MAX-4) {
844 nReturn = QCBOR_ERR_STRING_TOO_LONG;
845 goto Done;
846 }
847
848 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530849 if(UsefulBuf_IsNULLC(Bytes)) {
850 // Failed to get the bytes for this string item
851 nReturn = QCBOR_ERR_HIT_END;
852 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700853 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530854
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800855 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530856 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800857 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530858 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700859 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530860 goto Done;
861 }
862 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800863 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530864 } else {
865 // Normal case with no string allocator
866 pDecodedItem->val.string = Bytes;
867 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800868 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800869 // Cast because ternary operator causes promotion to integer
870 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
871 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800872
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530873Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700874 return nReturn;
875}
876
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700877
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800878
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700879
880
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700881
882
Laurence Lundbladeee851742020-01-08 08:37:05 -0800883// Make sure the constants align as this is assumed by
884// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700885#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
886#error QCBOR_TYPE_ARRAY value not lined up with major type
887#endif
888#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
889#error QCBOR_TYPE_MAP value not lined up with major type
890#endif
891
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700892/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800893 This gets a single data item and decodes it including preceding
894 optional tagging. This does not deal with arrays and maps and nesting
895 except to decode the data item introducing them. Arrays and maps are
896 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800897
Laurence Lundbladeee851742020-01-08 08:37:05 -0800898 Errors detected here include: an array that is too long to decode,
899 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700900 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800901static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
902 QCBORItem *pDecodedItem,
903 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700904{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700905 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800906
Laurence Lundbladeee851742020-01-08 08:37:05 -0800907 /*
908 Get the major type and the number. Number could be length of more
909 bytes or the value depending on the major type nAdditionalInfo is
910 an encoding of the length of the uNumber and is needed to decode
911 floats and doubles
912 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800913 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700914 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800915 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800916
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700917 memset(pDecodedItem, 0, sizeof(QCBORItem));
918
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800919 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800920
Laurence Lundbladeee851742020-01-08 08:37:05 -0800921 // Error out here if we got into trouble on the type and number. The
922 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700923 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700924 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700925 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800926
Laurence Lundbladeee851742020-01-08 08:37:05 -0800927 // At this point the major type and the value are valid. We've got
928 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800929 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700930 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
931 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800932 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700933 nReturn = QCBOR_ERR_BAD_INT;
934 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800935 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700936 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700937 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800938
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700939 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
940 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800941 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
942 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
943 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
944 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530945 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700946 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800947 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700948 }
949 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800950
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700951 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
952 case CBOR_MAJOR_TYPE_MAP: // Major type 5
953 // Record the number of items in the array or map
954 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
955 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
956 goto Done;
957 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800958 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700959 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700960 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800961 // type conversion OK because of check above
962 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700963 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800964 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800965 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
966 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700967 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800968
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700969 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800970 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700971 nReturn = QCBOR_ERR_BAD_INT;
972 } else {
973 pDecodedItem->val.uTagV = uNumber;
974 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
975 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700976 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800977
Laurence Lundbladeee851742020-01-08 08:37:05 -0800978 case CBOR_MAJOR_TYPE_SIMPLE:
979 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800980 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800982
Laurence Lundbladeee851742020-01-08 08:37:05 -0800983 default:
984 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700985 nReturn = QCBOR_ERR_UNSUPPORTED;
986 break;
987 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800988
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700989Done:
990 return nReturn;
991}
992
993
994
995/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800996 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800997 individual chunk items together into one QCBORItem using the string
998 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800999
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301000 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001001 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001002static inline QCBORError
1003GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001004{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001005 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001006
1007 // Get pointer to string allocator. First use is to pass it to
1008 // GetNext_Item() when option is set to allocate for *every* string.
1009 // Second use here is to allocate space to coallese indefinite
1010 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001011 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1012 &(me->StringAllocator) :
1013 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001014
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001015 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001016 nReturn = GetNext_Item(&(me->InBuf),
1017 pDecodedItem,
1018 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001019 if(nReturn) {
1020 goto Done;
1021 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001022
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001023 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301024 // code in this function from here down can be eliminated. Run tests, except
1025 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001026
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001027 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001028 const uint8_t uStringType = pDecodedItem->uDataType;
1029 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001030 goto Done; // no need to do any work here on non-string types
1031 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001032
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001033 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301034 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001035 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001036 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001037
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301038 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001039 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001040 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1041 goto Done;
1042 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001043
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001044 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001045 UsefulBufC FullString = NULLUsefulBufC;
1046
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001047 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001048 // Get item for next chunk
1049 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001050 // NULL string allocator passed here. Do not need to allocate
1051 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001052 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001054 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001055 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001056
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301057 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001058 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001059 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001060 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301061 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001062 break;
1063 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001064
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001065 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301066 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001067 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001068 if(StringChunkItem.uDataType != uStringType ||
1069 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001070 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001071 break;
1072 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001073
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301074 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001075 // The first time throurgh FullString.ptr is NULL and this is
1076 // equivalent to StringAllocator_Allocate()
1077 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1078 UNCONST_POINTER(FullString.ptr),
1079 FullString.len + StringChunkItem.val.string.len);
1080
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001081 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301082 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001083 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001084 break;
1085 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001086
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001087 // Copy new string chunk at the end of string so far.
1088 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001089 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001090
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001091 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1092 // Getting the item failed, clean up the allocated memory
1093 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001094 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001095
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001096Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001097 return nReturn;
1098}
1099
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001100
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001101static uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1102 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001103 return uTagVal;
1104 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001105 int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001106 return me->auMappedTags[x];
1107 }
1108}
1109
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001110/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001111 Gets all optional tag data items preceding a data item that is not an
1112 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001113 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001114static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001115GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001116{
Laurence Lundblade30816f22018-11-10 13:40:22 +07001117 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001118
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001119 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1120 CBOR_TAG_INVALID16,
1121 CBOR_TAG_INVALID16,
1122 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001123
Laurence Lundblade59289e52019-12-30 13:44:37 -08001124 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001125 for(;;) {
1126 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001127 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001128 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001129 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001130
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001131 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1132 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001133 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001134 break;
1135 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001136
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001137 // Is there room for the tag in the tags list?
1138 size_t uTagIndex;
1139 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001140 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001141 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001142 }
1143 }
1144 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001145 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001146 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001147
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001148 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001149 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001150 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001151 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001152 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001153 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001154 break;
1155 }
1156 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001157 // TODO: test this
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001158 break;
1159 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001160 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001161 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1162 // No room for the tag
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001163 // Should never happen as long as QCBOR_MAX_TAGS_PER_ITEM <= QCBOR_NUM_MAPPED_TAGS
1164 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001165 }
1166
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001167 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001168 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001169 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001170
1171 } else {
1172 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001173 }
1174 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001175
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001176Done:
1177 return nReturn;
1178}
1179
1180
1181/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001182 This layer takes care of map entries. It combines the label and data
1183 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001184 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001185static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001186GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001187{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001188 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001189 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001190 if(nReturn)
1191 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001192
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001193 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001194 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001195 goto Done;
1196 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001197
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001198 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1199 // In a map and caller wants maps decoded, not treated as arrays
1200
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001201 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001202 // If in a map and the right decoding mode, get the label
1203
Laurence Lundbladeee851742020-01-08 08:37:05 -08001204 // Save label in pDecodedItem and get the next which will
1205 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001206 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001207 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001208 if(nReturn)
1209 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001210
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301211 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001212
1213 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1214 // strings are always good labels
1215 pDecodedItem->label.string = LabelItem.val.string;
1216 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1217 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001218 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001219 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1220 goto Done;
1221 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1222 pDecodedItem->label.int64 = LabelItem.val.int64;
1223 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1224 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1225 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1226 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1227 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1228 pDecodedItem->label.string = LabelItem.val.string;
1229 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1230 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1231 } else {
1232 // label is not an int or a string. It is an arrray
1233 // or a float or such and this implementation doesn't handle that.
1234 // Also, tags on labels are ignored.
1235 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1236 goto Done;
1237 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001238 }
1239 } else {
1240 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001241 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1242 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1243 goto Done;
1244 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001245 // Decoding a map as an array
1246 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001247 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1248 // Cast is needed because of integer promotion
1249 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001250 }
1251 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001252
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001253Done:
1254 return nReturn;
1255}
1256
1257
Laurence Lundblade02625d42020-06-25 14:41:41 -07001258/*
1259 See if next item is a CBOR break. If it is, it is consumed,
1260 if not it is not consumed.
1261*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001262static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001263NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1264{
1265 *pbNextIsBreak = false;
1266 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001267 QCBORItem Peek;
1268 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1269 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1270 if(uReturn != QCBOR_SUCCESS) {
1271 return uReturn;
1272 }
1273 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001274 // It is not a break, rewind so it can be processed normally.
1275 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001276 } else {
1277 *pbNextIsBreak = true;
1278 }
1279 }
1280
1281 return QCBOR_SUCCESS;
1282}
1283
1284
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001285/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001286 An item was just consumed, now figure out if it was the
1287 end of an array or map that can be closed out. That
1288 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001289*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001290static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001291{
1292 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001293
Laurence Lundblade642282a2020-06-23 12:00:33 -07001294 /* This loops ascending nesting levels as long as there is ascending to do */
1295 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1296
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001297 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001298 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001299 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1300 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001301 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001302 break;
1303 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001304 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001305
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001306 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001307 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001308 bool bIsBreak = false;
1309 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1310 if(uReturn != QCBOR_SUCCESS) {
1311 goto Done;
1312 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001313
1314 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001315 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001316 break;
1317 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001318
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001319 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001320 /*
1321 Break occurred inside a bstr-wrapped CBOR or
1322 in the top level sequence. This is always an
1323 error because neither are an indefinte length
1324 map/array.
1325 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001326 uReturn = QCBOR_ERR_BAD_BREAK;
1327 goto Done;
1328 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001329 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001330 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001331
Laurence Lundblade02625d42020-06-25 14:41:41 -07001332 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001333
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001334 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001335 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001336 /* 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 -07001337 if(bMarkEnd) {
1338 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001339 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001340
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001341 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001342 break;
1343 }
1344
1345 /* Finally, actually ascend one level. */
1346 DecodeNesting_Ascend(&(pMe->nesting));
1347 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001348
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001349 uReturn = QCBOR_SUCCESS;
1350
1351Done:
1352 return uReturn;
1353}
1354
1355
1356/*
Laurence Lundblade642282a2020-06-23 12:00:33 -07001357 This the travesal going descending into and asecnding out of maps,
1358 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1359 indefinte length maps and arrays by looking at the item count or
1360 finding CBOR breaks. It detects the ends of the top-level sequence
1361 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001362 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001363static QCBORError
1364QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001365{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001366 QCBORError uReturn;
Laurence Lundblade642282a2020-06-23 12:00:33 -07001367 /* ==== First figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001368
Laurence Lundblade642282a2020-06-23 12:00:33 -07001369 /*
1370 If out of bytes to consume, it is either the end of the top-level
1371 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001372
Laurence Lundblade642282a2020-06-23 12:00:33 -07001373 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1374 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1375 CBOR is exited, the length is set back to the top-level's length
1376 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001377
Laurence Lundblade642282a2020-06-23 12:00:33 -07001378 Only return the success error code QCBOR_ERR_NO_MORE_ITEMS here
1379 when at the top level to allow other code below to process various
1380 errors when out of bytes to decode and not at the top level. Note
1381 that QCBORDecode_Finish() still needs to be called to be sure all
1382 nesting levels were closed out.
1383 */
1384 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 &&
1385 DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001386 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001387 goto Done;
1388 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001389
Laurence Lundblade642282a2020-06-23 12:00:33 -07001390 /*
1391 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001392 array. The check for the end of an indefinite length array is
1393 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001394 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001395 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001396 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001397 goto Done;
1398 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001399
Laurence Lundblade642282a2020-06-23 12:00:33 -07001400 /* ==== Next, not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001401 uReturn = GetNext_MapEntry(me, pDecodedItem);
1402 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001403 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001404 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301405
Laurence Lundblade642282a2020-06-23 12:00:33 -07001406 /*
1407 Breaks ending arrays/maps are always processed at the end of this
1408 function. They should never show up here.
1409 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301410 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001411 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301412 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301413 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001414
Laurence Lundblade642282a2020-06-23 12:00:33 -07001415 /*
1416 Record the nesting level for this data item before processing any
1417 of decrementing and descending.
1418 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001419 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001420
Laurence Lundblade642282a2020-06-23 12:00:33 -07001421
1422 /* ==== Next, Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001423 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001424 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001425 If the new item is a map or array descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001426
Laurence Lundblade02625d42020-06-25 14:41:41 -07001427 Empty maps and arrays descended into, but then ascended out
1428 of in the next chunk of code.
1429
1430 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001431 encloses them so a decrement needs to be done for them too, but
1432 that is done only when all the items in them have been
1433 processed, not when they are opened with the exception of an
1434 empty map or array.
1435 */
1436 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1437 pDecodedItem->uDataType,
1438 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001439 if(uReturn != QCBOR_SUCCESS) {
1440 goto Done;
1441 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001442 }
1443
Laurence Lundblade02625d42020-06-25 14:41:41 -07001444 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1445 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1446 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001447 /*
1448 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001449 - A non-aggregate like an integer or string
1450 - An empty definite length map or array
1451 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001452
1453 The Ascender does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001454 definite length map/array and break detection for an indefinite
1455 length map/array. If the end of the map/array was reached, then
1456 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001457 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001458 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001459 if(uReturn) {
1460 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001461 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301462 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001463
Laurence Lundblade02625d42020-06-25 14:41:41 -07001464 /* ==== Last, tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001465 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001466 Tell the caller what level is next. This tells them what
1467 maps/arrays were closed out and makes it possible for them to
1468 reconstruct the tree with just the information returned in
1469 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001470 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001471 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001472 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001473 pDecodedItem->uNextNestLevel = 0;
1474 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001475 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001476 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001477
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001478Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001479 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001480 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001481 memset(pDecodedItem, 0, sizeof(QCBORItem));
1482 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001483 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001484}
1485
1486
Laurence Lundblade59289e52019-12-30 13:44:37 -08001487/*
1488 Mostly just assign the right data type for the date string.
1489 */
1490inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1491{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001492 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1493 return QCBOR_ERR_BAD_OPT_TAG;
1494 }
1495
1496 const UsefulBufC Temp = pDecodedItem->val.string;
1497 pDecodedItem->val.dateString = Temp;
1498 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1499 return QCBOR_SUCCESS;
1500}
1501
1502
1503/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001504 The epoch formatted date. Turns lots of different forms of encoding
1505 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001506 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001507static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001508{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001509 QCBORError nReturn = QCBOR_SUCCESS;
1510
1511 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1512
1513 switch (pDecodedItem->uDataType) {
1514
1515 case QCBOR_TYPE_INT64:
1516 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1517 break;
1518
1519 case QCBOR_TYPE_UINT64:
1520 if(pDecodedItem->val.uint64 > INT64_MAX) {
1521 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1522 goto Done;
1523 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001524 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001525 break;
1526
1527 case QCBOR_TYPE_DOUBLE:
1528 {
1529 // This comparison needs to be done as a float before
1530 // conversion to an int64_t to be able to detect doubles
1531 // that are too large to fit into an int64_t. A double
1532 // has 52 bits of preceision. An int64_t has 63. Casting
1533 // INT64_MAX to a double actually causes a round up which
1534 // is bad and wrong for the comparison because it will
1535 // allow conversion of doubles that can't fit into a
1536 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1537 // the cutoff point as if that rounds up in conversion to
1538 // double it will still be less than INT64_MAX. 0x7ff is
1539 // picked because it has 11 bits set.
1540 //
1541 // INT64_MAX seconds is on the order of 10 billion years,
1542 // and the earth is less than 5 billion years old, so for
1543 // most uses this conversion error won't occur even though
1544 // doubles can go much larger.
1545 //
1546 // Without the 0x7ff there is a ~30 minute range of time
1547 // values 10 billion years in the past and in the future
1548 // where this this code would go wrong.
1549 const double d = pDecodedItem->val.dfnum;
1550 if(d > (double)(INT64_MAX - 0x7ff)) {
1551 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1552 goto Done;
1553 }
1554 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1555 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1556 }
1557 break;
1558
1559 default:
1560 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1561 goto Done;
1562 }
1563 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1564
1565Done:
1566 return nReturn;
1567}
1568
1569
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001570/*
1571 Mostly just assign the right data type for the bignum.
1572 */
1573inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1574{
1575 // Stack Use: UsefulBuf 1 -- 16
1576 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1577 return QCBOR_ERR_BAD_OPT_TAG;
1578 }
1579 const UsefulBufC Temp = pDecodedItem->val.string;
1580 pDecodedItem->val.bigNum = Temp;
1581 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1582 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1583 : QCBOR_TYPE_NEGBIGNUM);
1584 return QCBOR_SUCCESS;
1585}
1586
1587
Laurence Lundblade59289e52019-12-30 13:44:37 -08001588#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1589/*
1590 Decode decimal fractions and big floats.
1591
1592 When called pDecodedItem must be the array that is tagged as a big
1593 float or decimal fraction, the array that has the two members, the
1594 exponent and mantissa.
1595
1596 This will fetch and decode the exponent and mantissa and put the
1597 result back into pDecodedItem.
1598 */
1599inline static QCBORError
1600QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1601{
1602 QCBORError nReturn;
1603
1604 // --- Make sure it is an array; track nesting level of members ---
1605 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1606 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1607 goto Done;
1608 }
1609
1610 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001611 // definite length arrays, but not for indefnite. Instead remember
1612 // the nesting level the two integers must be at, which is one
1613 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001614 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1615
1616 // --- Is it a decimal fraction or a bigfloat? ---
1617 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1618 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1619
1620 // --- Get the exponent ---
1621 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001622 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001623 if(nReturn != QCBOR_SUCCESS) {
1624 goto Done;
1625 }
1626 if(exponentItem.uNestingLevel != nNestLevel) {
1627 // Array is empty or a map/array encountered when expecting an int
1628 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1629 goto Done;
1630 }
1631 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1632 // Data arriving as an unsigned int < INT64_MAX has been converted
1633 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1634 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1635 // will be too large for this to handle and thus an error that will
1636 // get handled in the next else.
1637 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1638 } else {
1639 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1640 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1641 goto Done;
1642 }
1643
1644 // --- Get the mantissa ---
1645 QCBORItem mantissaItem;
1646 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1647 if(nReturn != QCBOR_SUCCESS) {
1648 goto Done;
1649 }
1650 if(mantissaItem.uNestingLevel != nNestLevel) {
1651 // Mantissa missing or map/array encountered when expecting number
1652 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1653 goto Done;
1654 }
1655 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1656 // Data arriving as an unsigned int < INT64_MAX has been converted
1657 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1658 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1659 // will be too large for this to handle and thus an error that
1660 // will get handled in an else below.
1661 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1662 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1663 // Got a good big num mantissa
1664 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1665 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001666 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1667 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1668 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001669 } else {
1670 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1671 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1672 goto Done;
1673 }
1674
1675 // --- Check that array only has the two numbers ---
1676 if(mantissaItem.uNextNestLevel == nNestLevel) {
1677 // Extra items in the decimal fraction / big num
1678 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1679 goto Done;
1680 }
1681
1682Done:
1683
1684 return nReturn;
1685}
1686#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1687
1688
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001689
1690/*
1691 */
1692inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1693{
1694 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1695 return QCBOR_ERR_BAD_OPT_TAG;
1696 }
1697 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1698 return QCBOR_SUCCESS;
1699}
1700
1701
1702inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1703{
1704 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1705 return QCBOR_ERR_BAD_OPT_TAG;
1706 }
1707 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1708 return QCBOR_SUCCESS;
1709}
1710
1711
1712inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1713{
1714 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1715 return QCBOR_ERR_BAD_OPT_TAG;
1716 }
1717 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1718 return QCBOR_SUCCESS;
1719}
1720
1721
1722inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1723{
1724 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1725 return QCBOR_ERR_BAD_OPT_TAG;
1726 }
1727 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1728 return QCBOR_SUCCESS;
1729}
1730
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001731inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1732{
1733 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1734 return QCBOR_ERR_BAD_OPT_TAG;
1735 }
1736 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1737 return QCBOR_SUCCESS;
1738}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001739
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001740
1741inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1742{
1743 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1744 return QCBOR_ERR_BAD_OPT_TAG;
1745 }
1746 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
1747 return QCBOR_SUCCESS;
1748}
1749
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001750inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1751{
1752 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1753 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
1754 } else if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1755 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1756 } else {
1757 return QCBOR_ERR_BAD_OPT_TAG;
1758 }
1759 return QCBOR_SUCCESS;
1760}
1761
1762
1763/*
1764 */
1765inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1766{
1767 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1768 return QCBOR_ERR_BAD_OPT_TAG;
1769 }
1770 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1771 return QCBOR_SUCCESS;
1772}
1773
1774
Laurence Lundblade59289e52019-12-30 13:44:37 -08001775/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001776 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001777 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001778QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001779QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001780{
1781 QCBORError nReturn;
1782
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001783 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001784 if(nReturn != QCBOR_SUCCESS) {
1785 goto Done;
1786 }
1787
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001788 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1789 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001790
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001791 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001792 nReturn = DecodeDateString(pDecodedItem);
1793 break;
1794
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001795 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001796 nReturn = DecodeDateEpoch(pDecodedItem);
1797 break;
1798
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001799 case CBOR_TAG_POS_BIGNUM:
1800 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001801 nReturn = DecodeBigNum(pDecodedItem);
1802 break;
1803
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001804 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1805 case CBOR_TAG_DECIMAL_FRACTION:
1806 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001807 // For aggregate tagged types, what goes into pTags is only collected
1808 // from the surrounding data item, not the contents, so pTags is not
1809 // passed on here.
1810
1811 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1812 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001813 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001814
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001815 case CBOR_TAG_CBOR:
1816 nReturn = DecodeWrappedCBOR(pDecodedItem);
1817 break;
1818
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001819 case CBOR_TAG_CBOR_SEQUENCE:
1820 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1821 break;
1822
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001823 case CBOR_TAG_URI:
1824 nReturn = DecodeURI(pDecodedItem);
1825 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001826
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001827 case CBOR_TAG_B64URL:
1828 nReturn = DecodeB64URL(pDecodedItem);
1829 break;
1830
1831 case CBOR_TAG_B64:
1832 nReturn = DecodeB64(pDecodedItem);
1833 break;
1834
1835 case CBOR_TAG_MIME:
1836 case CBOR_TAG_BINARY_MIME:
1837 nReturn = DecodeMIME(pDecodedItem);
1838 break;
1839
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001840 case CBOR_TAG_REGEX:
1841 nReturn = DecodeRegex(pDecodedItem);
1842 break;
1843
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001844 case CBOR_TAG_BIN_UUID:
1845 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001846 break;
1847
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001848 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001849 // The end of the tag list or no tags
1850 // Successful exit from the loop.
1851 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001852
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001853 default:
1854 // A tag that is not understood
1855 // A successful exit from the loop
1856 goto Done;
1857
1858 }
1859 if(nReturn != QCBOR_SUCCESS) {
1860 goto Done;
1861 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001862 }
1863
1864Done:
1865 if(nReturn != QCBOR_SUCCESS) {
1866 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1867 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1868 }
1869 return nReturn;
1870}
1871
1872
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001873QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1874{
1875 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1876
1877 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1878
1879 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1880
1881 return uErr;
1882}
1883
1884
Laurence Lundblade59289e52019-12-30 13:44:37 -08001885/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001886 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001887 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001888QCBORError
1889QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1890 QCBORItem *pDecodedItem,
1891 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001892{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001893 QCBORError nReturn;
1894
1895 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1896 if(nReturn != QCBOR_SUCCESS) {
1897 return nReturn;
1898 }
1899
1900 if(pTags != NULL) {
1901 pTags->uNumUsed = 0;
1902 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001903 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001904 break;
1905 }
1906 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1907 return QCBOR_ERR_TOO_MANY_TAGS;
1908 }
1909 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1910 pTags->uNumUsed++;
1911 }
1912 }
1913
1914 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001915}
1916
1917
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001918/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301919 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301920 next one down. If a layer has no work to do for a particular item
1921 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001922
Laurence Lundblade59289e52019-12-30 13:44:37 -08001923 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1924 tagged data items, turning them into the local C representation.
1925 For the most simple it is just associating a QCBOR_TYPE with the data. For
1926 the complex ones that an aggregate of data items, there is some further
1927 decoding and a little bit of recursion.
1928
1929 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301930 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301931 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001932 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001933
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301934 - GetNext_MapEntry -- This handles the combining of two
1935 items, the label and the data, that make up a map entry.
1936 It only does work on maps. It combines the label and data
1937 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001938
Laurence Lundblade59289e52019-12-30 13:44:37 -08001939 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1940 tags into bit flags associated with the data item. No actual decoding
1941 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001942
Laurence Lundblade59289e52019-12-30 13:44:37 -08001943 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301944 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301945 string allocater to create contiguous space for the item. It
1946 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001947
Laurence Lundblade59289e52019-12-30 13:44:37 -08001948 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1949 atomic data item has a "major type", an integer "argument" and optionally
1950 some content. For text and byte strings, the content is the bytes
1951 that make up the string. These are the smallest data items that are
1952 considered to be well-formed. The content may also be other data items in
1953 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001954
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001955 Roughly this takes 300 bytes of stack for vars. Need to
1956 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001957
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301958 */
1959
1960
1961/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001962 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001963 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001964int QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001965 const QCBORItem *pItem,
1966 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001967{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001968 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001969 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001970 break;
1971 }
1972 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1973 return 1;
1974 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001975 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001976
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001977 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001978}
1979
1980
1981/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001982 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001983 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001984QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001985{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001986 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001987
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001988 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001989 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001990 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1991 goto Done;
1992 }
1993
1994 // Error out if not all the bytes are consumed
1995 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1996 nReturn = QCBOR_ERR_EXTRA_BYTES;
1997 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001998
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001999Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302000 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002001 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002002 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002003
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002004 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002005}
2006
2007
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002008/*
2009Public function, see header qcbor/qcbor_decode.h file
2010*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002011uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2012 const QCBORItem *pItem,
2013 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002014{
2015 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
2016 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002017 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002018 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002019 }
2020}
2021
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002022
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002023/*
2024
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002025Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002026
Laurence Lundbladeee851742020-01-08 08:37:05 -08002027 - Hit end of input before it was expected while decoding type and
2028 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002029
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002030 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002031
Laurence Lundbladeee851742020-01-08 08:37:05 -08002032 - Hit end of input while decoding a text or byte string
2033 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002034
Laurence Lundbladeee851742020-01-08 08:37:05 -08002035 - Encountered conflicting tags -- e.g., an item is tagged both a date
2036 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002037
Laurence Lundbladeee851742020-01-08 08:37:05 -08002038 - Encontered an array or mapp that has too many items
2039 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002040
Laurence Lundbladeee851742020-01-08 08:37:05 -08002041 - Encountered array/map nesting that is too deep
2042 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002043
Laurence Lundbladeee851742020-01-08 08:37:05 -08002044 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2045 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002046
Laurence Lundbladeee851742020-01-08 08:37:05 -08002047 - The type of a map label is not a string or int
2048 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002049
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002050 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002051
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002052 */
2053
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002054
2055
Laurence Lundbladef6531662018-12-04 10:42:22 +09002056
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002057/* ===========================================================================
2058 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002059
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002060 This implements a simple sting allocator for indefinite length
2061 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2062 implements the function type QCBORStringAllocate and allows easy
2063 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002064
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002065 This particular allocator is built-in for convenience. The caller
2066 can implement their own. All of this following code will get
2067 dead-stripped if QCBORDecode_SetMemPool() is not called.
2068
2069 This is a very primitive memory allocator. It does not track
2070 individual allocations, only a high-water mark. A free or
2071 reallocation must be of the last chunk allocated.
2072
2073 The size of the pool and offset to free memory are packed into the
2074 first 8 bytes of the memory pool so we don't have to keep them in
2075 the decode context. Since the address of the pool may not be
2076 aligned, they have to be packed and unpacked as if they were
2077 serialized data of the wire or such.
2078
2079 The sizes packed in are uint32_t to be the same on all CPU types
2080 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002081 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002082
2083
Laurence Lundbladeee851742020-01-08 08:37:05 -08002084static inline int
2085MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002086{
2087 // Use of UsefulInputBuf is overkill, but it is convenient.
2088 UsefulInputBuf UIB;
2089
Laurence Lundbladeee851742020-01-08 08:37:05 -08002090 // Just assume the size here. It was checked during SetUp so
2091 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002092 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2093 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2094 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2095 return UsefulInputBuf_GetError(&UIB);
2096}
2097
2098
Laurence Lundbladeee851742020-01-08 08:37:05 -08002099static inline int
2100MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002101{
2102 // Use of UsefulOutBuf is overkill, but convenient. The
2103 // length check performed here is useful.
2104 UsefulOutBuf UOB;
2105
2106 UsefulOutBuf_Init(&UOB, Pool);
2107 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2108 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2109 return UsefulOutBuf_GetError(&UOB);
2110}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002111
2112
2113/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002114 Internal function for an allocation, reallocation free and destuct.
2115
2116 Having only one function rather than one each per mode saves space in
2117 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002118
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002119 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2120 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002121static UsefulBuf
2122MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002123{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002124 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002125
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002126 uint32_t uPoolSize;
2127 uint32_t uFreeOffset;
2128
2129 if(uNewSize > UINT32_MAX) {
2130 // This allocator is only good up to 4GB. This check should
2131 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2132 goto Done;
2133 }
2134 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2135
2136 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2137 goto Done;
2138 }
2139
2140 if(uNewSize) {
2141 if(pMem) {
2142 // REALLOCATION MODE
2143 // Calculate pointer to the end of the memory pool. It is
2144 // assumed that pPool + uPoolSize won't wrap around by
2145 // assuming the caller won't pass a pool buffer in that is
2146 // not in legitimate memory space.
2147 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2148
2149 // Check that the pointer for reallocation is in the range of the
2150 // pool. This also makes sure that pointer math further down
2151 // doesn't wrap under or over.
2152 if(pMem >= pPool && pMem < pPoolEnd) {
2153 // Offset to start of chunk for reallocation. This won't
2154 // wrap under because of check that pMem >= pPool. Cast
2155 // is safe because the pool is always less than UINT32_MAX
2156 // because of check in QCBORDecode_SetMemPool().
2157 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2158
2159 // Check to see if the allocation will fit. uPoolSize -
2160 // uMemOffset will not wrap under because of check that
2161 // pMem is in the range of the uPoolSize by check above.
2162 if(uNewSize <= uPoolSize - uMemOffset) {
2163 ReturnValue.ptr = pMem;
2164 ReturnValue.len = uNewSize;
2165
2166 // Addition won't wrap around over because uNewSize was
2167 // checked to be sure it is less than the pool size.
2168 uFreeOffset = uMemOffset + uNewSize32;
2169 }
2170 }
2171 } else {
2172 // ALLOCATION MODE
2173 // uPoolSize - uFreeOffset will not underflow because this
2174 // pool implementation makes sure uFreeOffset is always
2175 // smaller than uPoolSize through this check here and
2176 // reallocation case.
2177 if(uNewSize <= uPoolSize - uFreeOffset) {
2178 ReturnValue.len = uNewSize;
2179 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002180 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002181 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002182 }
2183 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002184 if(pMem) {
2185 // FREE MODE
2186 // Cast is safe because of limit on pool size in
2187 // QCBORDecode_SetMemPool()
2188 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2189 } else {
2190 // DESTRUCT MODE
2191 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002192 }
2193 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002194
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002195 UsefulBuf Pool = {pPool, uPoolSize};
2196 MemPool_Pack(Pool, uFreeOffset);
2197
2198Done:
2199 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002200}
2201
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002202
Laurence Lundbladef6531662018-12-04 10:42:22 +09002203/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002204 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002205 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002206QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2207 UsefulBuf Pool,
2208 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002209{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002210 // The pool size and free mem offset are packed into the beginning
2211 // of the pool memory. This compile time check make sure the
2212 // constant in the header is correct. This check should optimize
2213 // down to nothing.
2214 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002215 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002216 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002217
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002218 // The pool size and free offset packed in to the beginning of pool
2219 // memory are only 32-bits. This check will optimize out on 32-bit
2220 // machines.
2221 if(Pool.len > UINT32_MAX) {
2222 return QCBOR_ERR_BUFFER_TOO_LARGE;
2223 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002224
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002225 // This checks that the pool buffer given is big enough.
2226 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2227 return QCBOR_ERR_BUFFER_TOO_SMALL;
2228 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002229
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002230 pMe->StringAllocator.pfAllocator = MemPool_Function;
2231 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2232 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002233
Laurence Lundblade30816f22018-11-10 13:40:22 +07002234 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002235}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002236
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002237
2238
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002239
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002240
2241
2242/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002243 Consume an entire map or array (and do next to
2244 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002245 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002246static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002247ConsumeItem(QCBORDecodeContext *pMe,
2248 const QCBORItem *pItemToConsume,
2249 uint_fast8_t *puNextNestLevel)
2250{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002251 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002252 QCBORItem Item;
2253
Laurence Lundblade02625d42020-06-25 14:41:41 -07002254 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002255
Laurence Lundblade02625d42020-06-25 14:41:41 -07002256 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002257 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002258
Laurence Lundblade1341c592020-04-11 14:19:05 -07002259 /* This works for definite and indefinite length
2260 * maps and arrays by using the nesting level
2261 */
2262 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002263 uReturn = QCBORDecode_GetNext(pMe, &Item);
2264 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002265 goto Done;
2266 }
2267 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002268
Laurence Lundblade1341c592020-04-11 14:19:05 -07002269 if(puNextNestLevel != NULL) {
2270 *puNextNestLevel = Item.uNextNestLevel;
2271 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002272 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002273
Laurence Lundblade1341c592020-04-11 14:19:05 -07002274 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002275 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002276 if(puNextNestLevel != NULL) {
2277 /* Just pass the nesting level through */
2278 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2279 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002280 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002281 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002282
2283Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002284 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002285}
2286
2287
Laurence Lundblade1341c592020-04-11 14:19:05 -07002288/* Return true if the labels in Item1 and Item2 are the same.
2289 Works only for integer and string labels. Returns false
2290 for any other type. */
2291static inline bool
2292MatchLabel(QCBORItem Item1, QCBORItem Item2)
2293{
2294 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2295 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2296 return true;
2297 }
2298 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002299 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002300 return true;
2301 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002302 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002303 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2304 return true;
2305 }
2306 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2307 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2308 return true;
2309 }
2310 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002311
Laurence Lundblade1341c592020-04-11 14:19:05 -07002312 /* Other label types are never matched */
2313 return false;
2314}
2315
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002316
2317/*
2318 Returns true if Item1 and Item2 are the same type
2319 or if either are of QCBOR_TYPE_ANY.
2320 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002321static inline bool
2322MatchType(QCBORItem Item1, QCBORItem Item2)
2323{
2324 if(Item1.uDataType == Item2.uDataType) {
2325 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002326 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002327 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002328 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002329 return true;
2330 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002331 return false;
2332}
2333
2334
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002335/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002336 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002337
2338 @param[in] pMe The decode context to search.
2339 @param[in,out] pItemArray The items to search for and the items found.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002340 @param[out] puOffset Byte offset of last item matched.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002341 @param[in] pCBContext Context for the not-found item call back
2342 @param[in] pfCallback Function to call on items not matched in pItemArray
2343
2344 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2345
2346 @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.
2347
2348 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2349
2350 @retval Also errors returned by QCBORDecode_GetNext().
2351
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002352 On input pItemArray contains a list of labels and data types
2353 of items to be found.
2354
2355 On output the fully retrieved items are filled in with
2356 values and such. The label was matched, so it never changes.
2357
2358 If an item was not found, its data type is set to none.
2359
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002360 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002361static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002362MapSearch(QCBORDecodeContext *pMe,
2363 QCBORItem *pItemArray,
2364 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002365 void *pCBContext,
2366 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002367{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002368 QCBORError uReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002369
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002370 QCBORDecodeNesting SaveNesting;
2371 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002372
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002373 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
2374 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2375 /* QCBOR_TYPE_NONE as first item indicates just looking
2376 for the end of an array, so don't give error. */
2377 uReturn = QCBOR_ERR_NOT_A_MAP;
2378 goto Done;
2379 }
2380
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002381 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002382 UsefulInputBuf_Seek(&(pMe->InBuf),
2383 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002384
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002385 /*
2386 Loop over all the items in the map. They could be
2387 deeply nested and this should handle both definite
2388 and indefinite length maps and arrays, so this
2389 adds some complexity.
2390 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002391 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002392
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002393 uint_fast8_t uNextNestLevel;
2394
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002395 uint64_t uFoundItemBitMap = 0;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002396
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002397 /* Iterate over items in the map / array */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002398 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002399 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002400 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002401
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002402 /* Get the item */
2403 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002404 uReturn = QCBORDecode_GetNext(pMe, &Item);
2405 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002406 /* Got non-well-formed CBOR */
2407 goto Done;
2408 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002409
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002410 /* See if item has one of the labels that are of interest */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002411 int nIndex;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002412 QCBORItem *pIterator;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002413 for(pIterator = pItemArray, nIndex = 0; pIterator->uLabelType != 0; pIterator++, nIndex++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002414 if(MatchLabel(Item, *pIterator)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002415 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002416 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2417 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002418 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002419 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002420 /* Also try to match its type */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002421 if(!MatchType(Item, *pIterator)) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002422 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002423 goto Done;
2424 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002425
2426 /* Successful match. Return the item. */
2427 *pIterator = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002428 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002429 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002430 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002431 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002432 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002433 /*
2434 Call the callback on unmatched labels.
2435 (It is tempting to do duplicate detection here, but that would
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002436 require dynamic memory allocation because the number of labels
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002437 that might be encountered is unbounded.)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002438 */
2439 if(pfCallback) {
2440 uReturn = (*pfCallback)(pCBContext, &Item);
2441 if(uReturn != QCBOR_SUCCESS) {
2442 goto Done;
2443 }
2444 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002445 }
2446 }
2447
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002448 /*
2449 Consume the item whether matched or not. This
2450 does the work of traversing maps and array and
2451 everything in them. In this loop only the
2452 items at the current nesting level are examined
2453 to match the labels.
2454 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002455 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2456 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002457 goto Done;
2458 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002459
2460 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002461
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002462 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002463
2464 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002465 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2466 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002467
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002468 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002469 int i;
2470 QCBORItem *pIterator;
2471 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002472 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002473 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002474 }
2475 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002476
2477Done:
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002478 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002479
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002480 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002481}
2482
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002483
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002484/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002485 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002486*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002487void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2488 int64_t nLabel,
2489 uint8_t uQcborType,
2490 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002491{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002492 if(pMe->uLastError != QCBOR_SUCCESS) {
2493 return;
2494 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002495
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002496 QCBORItem OneItemSeach[2];
2497 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2498 OneItemSeach[0].label.int64 = nLabel;
2499 OneItemSeach[0].uDataType = uQcborType;
2500 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002501
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002502 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2503 if(uReturn != QCBOR_SUCCESS) {
2504 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002505 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002506 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002507 uReturn = QCBOR_ERR_NOT_FOUND;
2508 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002509 }
2510
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002511 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002512
2513 Done:
2514 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002515}
2516
2517
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002518/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002519 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002520*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002521void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2522 const char *szLabel,
2523 uint8_t uQcborType,
2524 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002525{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002526 if(pMe->uLastError != QCBOR_SUCCESS) {
2527 return;
2528 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002529
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002530 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002531 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2532 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2533 OneItemSeach[0].uDataType = uQcborType;
2534 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002535
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002536 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2537 if(uReturn != QCBOR_SUCCESS) {
2538 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002539 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002540 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002541 uReturn = QCBOR_ERR_NOT_FOUND;
2542 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002543 }
2544
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002545 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002546
2547Done:
2548 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002549}
2550
2551
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002552
2553static QCBORError CheckTypeList(uint8_t uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
2554{
2555 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2556 if(uDataType == puTypeList[i]) {
2557 return QCBOR_SUCCESS;
2558 }
2559 }
2560 return QCBOR_ERR_UNEXPECTED_TYPE;
2561}
2562
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002563/**
2564 @param[in] TagSpec Specification for matching tags.
2565 @param[in] uDataType A QCBOR data type
2566
2567 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2568 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2569
2570 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2571 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002572static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002573{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002574 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002575 // Must match the tag and only the tag
2576 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002577 }
2578
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002579 QCBORError uReturn = CheckTypeList(uDataType, TagSpec.uAllowedContentTypes);
2580 if(uReturn == QCBOR_SUCCESS) {
2581 return QCBOR_SUCCESS;
2582 }
2583
2584 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
2585 /* Must match the content type and only the content type.
2586 There was no match just above so it is a fail. */
2587 return QCBOR_ERR_UNEXPECTED_TYPE;
2588 }
2589
2590 /* If here it can match either the tag or the content
2591 and it hasn't matched the content, so the end
2592 result is whether it matches the tag. This is
2593 also the case that the CBOR standard discourages. */
2594
2595 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002596}
2597
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002598
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002599// Semi-private
2600// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002601void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2602 int64_t nLabel,
2603 TagSpecification TagSpec,
2604 QCBORItem *pItem)
2605{
2606 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2607 if(pMe->uLastError != QCBOR_SUCCESS) {
2608 return;
2609 }
2610
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002611 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002612}
2613
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002614// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002615void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2616 const char *szLabel,
2617 TagSpecification TagSpec,
2618 QCBORItem *pItem)
2619{
2620 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2621 if(pMe->uLastError != QCBOR_SUCCESS) {
2622 return;
2623 }
2624
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002625 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002626}
2627
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002628// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002629void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2630 int64_t nLabel,
2631 TagSpecification TagSpec,
2632 UsefulBufC *pString)
2633{
2634 QCBORItem Item;
2635 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2636 if(pMe->uLastError == QCBOR_SUCCESS) {
2637 *pString = Item.val.string;
2638 }
2639}
2640
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002641// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002642void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2643 const char * szLabel,
2644 TagSpecification TagSpec,
2645 UsefulBufC *pString)
2646{
2647 QCBORItem Item;
2648 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2649 if(pMe->uLastError == QCBOR_SUCCESS) {
2650 *pString = Item.val.string;
2651 }
2652}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002653
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002654/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002655 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002656*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002657QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2658{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002659 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002660}
2661
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002662/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002663 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002664*/
2665QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2666 QCBORItem *pItemList,
2667 void *pCallbackCtx,
2668 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002669{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002670 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002671}
2672
2673
Laurence Lundblade34691b92020-05-18 22:25:25 -07002674static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002675{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002676 if(pMe->uLastError != QCBOR_SUCCESS) {
2677 // Already in error state; do nothing.
2678 return;
2679 }
2680
2681 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002682 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002683 if(pMe->uLastError != QCBOR_SUCCESS) {
2684 return;
2685 }
2686
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002687 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002688 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002689
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002690 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002691 be at the right place.
2692
2693 The UsefulInBuf offset could be anywhere, so no assumption is
2694 made about it.
2695
2696 No assumption is made about the pre-order nesting level either.
2697
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002698 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002699 the map level that is being entered.
2700 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002701 /* Seek to the data item that is the map or array */
2702 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002703
2704 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002705
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002706 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002707}
2708
2709
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002710/*
2711Public function, see header qcbor/qcbor_decode.h file
2712*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002713void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002714{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002715 QCBORItem OneItemSeach[2];
2716 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2717 OneItemSeach[0].label.int64 = nLabel;
2718 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2719 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002720
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002721 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002722 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002723}
2724
2725
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002726/*
2727Public function, see header qcbor/qcbor_decode.h file
2728*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002729void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002730{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002731 QCBORItem OneItemSeach[2];
2732 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2733 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2734 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2735 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002736
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002737 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002738}
2739
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002740/*
2741Public function, see header qcbor/qcbor_decode.h file
2742*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002743void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002744{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002745 QCBORItem OneItemSeach[2];
2746 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2747 OneItemSeach[0].label.int64 = nLabel;
2748 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2749 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002750
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002751 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002752}
2753
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002754/*
2755Public function, see header qcbor/qcbor_decode.h file
2756*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002757void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2758{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002759 QCBORItem OneItemSeach[2];
2760 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2761 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2762 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2763 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002764
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002765 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002766}
2767
2768
Laurence Lundblade02625d42020-06-25 14:41:41 -07002769// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002770void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002771{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002772 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002773 if(pMe->uLastError != QCBOR_SUCCESS) {
2774 // Already in error state; do nothing.
2775 return;
2776 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002777
2778 /* Get the data item that is the map that is being searched */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002779 QCBORItem Item;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002780 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002781 if(pMe->uLastError != QCBOR_SUCCESS) {
2782 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002783 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002784 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002785 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2786 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002787 }
2788
Laurence Lundblade02625d42020-06-25 14:41:41 -07002789 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002790
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002791 QCBORError uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting),
2792 UsefulInputBuf_Tell(&(pMe->InBuf)));
2793
2794 pMe->uLastError = (uint8_t)uErr;
2795
Laurence Lundblade02625d42020-06-25 14:41:41 -07002796 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002797}
2798
Laurence Lundblade02625d42020-06-25 14:41:41 -07002799
2800/*
2801 This is for exiting a level that is a bounded map, array or bstr
2802 wrapped CBOR. It is the work common to these.
2803
2804 One chunk of work is to set up the pre-order traversal so it is at
2805 the item just after the bounded map, array or bstr that is being
2806 exited. This is somewhat complex.
2807
2808 The other work is to level-up the bounded mode to next higest bounded
2809 mode or the top level if there isn't one.
2810 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002811static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002812ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002813{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002814 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002815
Laurence Lundblade02625d42020-06-25 14:41:41 -07002816 /*
2817 First the pre-order-traversal byte offset is positioned to the
2818 item just after the bounded mode item that was just consumed.
2819 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002820 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2821
Laurence Lundblade02625d42020-06-25 14:41:41 -07002822 /*
2823 Next, set the current nesting level to one above the bounded level
2824 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002825
Laurence Lundblade02625d42020-06-25 14:41:41 -07002826 DecodeNesting_CheckBoundedType() is always called before this and
2827 makes sure pCurrentBounded is valid.
2828 */
2829 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2830
2831 /*
2832 This does the complex work of leveling up the pre-order traversal
2833 when the end of a map or array or another bounded level is
2834 reached. It may do nothing, or ascend all the way to the top
2835 level.
2836 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07002837 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002838 if(uErr != QCBOR_SUCCESS) {
2839 goto Done;
2840 }
2841
Laurence Lundblade02625d42020-06-25 14:41:41 -07002842 /*
2843 This makes the next highest bounded level the current bounded
2844 level. If there is no next highest level, then no bounded mode is
2845 in effect.
2846 */
2847 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002848
Laurence Lundblade02625d42020-06-25 14:41:41 -07002849 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002850
2851Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002852 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002853 return uErr;
2854}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002855
Laurence Lundblade02625d42020-06-25 14:41:41 -07002856
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002857// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002858void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002859{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002860 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002861 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002862 return;
2863 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002864
Laurence Lundblade02625d42020-06-25 14:41:41 -07002865 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002866
Laurence Lundblade02625d42020-06-25 14:41:41 -07002867 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002868 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2869 goto Done;
2870 }
2871
Laurence Lundblade02625d42020-06-25 14:41:41 -07002872 /*
2873 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002874 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002875 from previous map search, then do a dummy search.
2876 */
2877 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002878 QCBORItem Dummy;
2879 Dummy.uLabelType = QCBOR_TYPE_NONE;
2880 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2881 if(uErr != QCBOR_SUCCESS) {
2882 goto Done;
2883 }
2884 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002885
Laurence Lundblade02625d42020-06-25 14:41:41 -07002886 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002887
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002888Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002889 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002890}
2891
2892
Laurence Lundblade1341c592020-04-11 14:19:05 -07002893void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002894{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002895 // TODO: check for map mode; test this
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002896 //pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->u.ma.uCountTotal;
2897 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->u.ma.uStartOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002898}
2899
2900
Laurence Lundblade1341c592020-04-11 14:19:05 -07002901
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002902static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002903 const QCBORItem *pItem,
2904 uint8_t uTagRequirement,
2905 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002906{
2907 if(pMe->uLastError != QCBOR_SUCCESS) {
2908 // Already in error state; do nothing.
2909 return pMe->uLastError;
2910 }
2911
2912 QCBORError uError = QCBOR_SUCCESS;
2913
2914 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2915 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2916 goto Done;;
2917 }
2918
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002919 const TagSpecification TagSpec = {uTagRequirement,
2920 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
2921 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
2922 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002923
2924 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2925 if(uError != QCBOR_SUCCESS) {
2926 goto Done;
2927 }
2928
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002929 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002930 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002931 so the increment in NestLevelAscender called by ExitBoundedLevel()
2932 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002933 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002934 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002935
2936 if(pBstr) {
2937 *pBstr = pItem->val.string;
2938 }
2939
2940 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002941
2942 // Need to move UIB input cursor to the right place
2943
2944 // Really this is a subtraction and an assignment; not much code
2945 // There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002946 // The bstr was just consumed so the cursor is at the next item after it
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002947
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002948 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002949
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002950 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
2951
2952 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002953
Laurence Lundblade02625d42020-06-25 14:41:41 -07002954 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
2955 uPreviousLength,
2956 uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002957Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002958 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002959
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002960 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002961}
2962
2963
Laurence Lundblade02625d42020-06-25 14:41:41 -07002964/*
2965 Public function, see header qcbor/qcbor_decode.h file
2966 */
2967void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002968 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002969 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002970{
2971 if(pMe->uLastError != QCBOR_SUCCESS) {
2972 // Already in error state; do nothing.
2973 return;
2974 }
2975
2976 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002977 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002978 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
2979 if(pMe->uLastError != QCBOR_SUCCESS) {
2980 return;
2981 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002982
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002983 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002984 &Item,
2985 uTagRequirement,
2986 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002987}
2988
2989
Laurence Lundblade02625d42020-06-25 14:41:41 -07002990/*
2991 Public function, see header qcbor/qcbor_decode.h file
2992 */
2993void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
2994 uint8_t uTagRequirement,
2995 int64_t nLabel,
2996 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002997{
2998 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002999 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003000
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003001 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003002}
3003
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003004
Laurence Lundblade02625d42020-06-25 14:41:41 -07003005/*
3006 Public function, see header qcbor/qcbor_decode.h file
3007 */
3008void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
3009 uint8_t uTagRequirement,
3010 const char *szLabel,
3011 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003012{
3013 QCBORItem Item;
3014 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3015
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003016 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003017}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003018
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003019
Laurence Lundblade02625d42020-06-25 14:41:41 -07003020/*
3021 Public function, see header qcbor/qcbor_decode.h file
3022 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003023void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003024{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003025 if(pMe->uLastError != QCBOR_SUCCESS) {
3026 // Already in error state; do nothing.
3027 return;
3028 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003029
Laurence Lundblade02625d42020-06-25 14:41:41 -07003030 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3031 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3032 return;
3033 }
3034
3035 /*
3036 Reset the length of the UsefulInputBuf to what it was before
3037 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003038 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003039 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3040 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003041
3042
Laurence Lundblade02625d42020-06-25 14:41:41 -07003043 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003044 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003045}
3046
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003047
Laurence Lundbladee6430642020-03-14 21:15:44 -07003048
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003049
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003050
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003051
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003052
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003053
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003054static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3055{
3056 switch(pItem->uDataType) {
3057 case QCBOR_TYPE_TRUE:
3058 *pBool = true;
3059 return QCBOR_SUCCESS;
3060 break;
3061
3062 case QCBOR_TYPE_FALSE:
3063 *pBool = false;
3064 return QCBOR_SUCCESS;
3065 break;
3066
3067 default:
3068 return QCBOR_ERR_UNEXPECTED_TYPE;
3069 break;
3070 }
3071}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003072
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003073/*
3074Public function, see header qcbor/qcbor_decode.h file
3075*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003076void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003077{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003078 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003079 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003080 return;
3081 }
3082
Laurence Lundbladec4537442020-04-14 18:53:22 -07003083 QCBORError nError;
3084 QCBORItem Item;
3085
3086 nError = QCBORDecode_GetNext(pMe, &Item);
3087 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003088 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003089 return;
3090 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003091 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003092}
3093
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003094/*
3095Public function, see header qcbor/qcbor_decode.h file
3096*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003097void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003098{
3099 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003100 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003101
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003102 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003103}
3104
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003105/*
3106Public function, see header qcbor/qcbor_decode.h file
3107*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003108void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3109{
3110 QCBORItem Item;
3111 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3112
3113 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3114}
3115
3116
3117
3118void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003119{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003120 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003121 // Already in error state, do nothing
3122 return;
3123 }
3124
3125 QCBORError nError;
3126 QCBORItem Item;
3127
3128 nError = QCBORDecode_GetNext(pMe, &Item);
3129 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003130 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003131 return;
3132 }
3133
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003134 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3135
3136 if(pMe->uLastError == QCBOR_SUCCESS) {
3137 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003138 }
3139}
3140
Laurence Lundbladec4537442020-04-14 18:53:22 -07003141
3142
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003143
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003144static QCBORError ConvertBigNum(uint8_t uTagRequirement,
3145 const QCBORItem *pItem,
3146 UsefulBufC *pValue,
3147 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003148{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003149 const TagSpecification TagSpec = {uTagRequirement,
3150 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3151 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3152 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003153
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003154 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
3155 if(uErr != QCBOR_SUCCESS) {
3156 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003157 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003158
3159 *pValue = pItem->val.string;
3160
3161 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3162 *pbIsNegative = false;
3163 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3164 *pbIsNegative = true;
3165 }
3166
3167 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003168}
3169
3170
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003171/**
3172 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003173 */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003174void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003175{
3176 if(pMe->uLastError != QCBOR_SUCCESS) {
3177 // Already in error state, do nothing
3178 return;
3179 }
3180
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003181 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003182 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3183 if(uError != QCBOR_SUCCESS) {
3184 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003185 return;
3186 }
3187
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003188 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003189}
3190
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003191/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003192Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003193*/
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003194void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003195{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003196 QCBORItem Item;
3197 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003198
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003199 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003200}
3201
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003202/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003203Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003204*/
3205void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
3206{
3207 QCBORItem Item;
3208 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3209
3210 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
3211}
3212
3213
3214
3215// Semi private
3216QCBORError FarfMIME(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsNot7Bit)
3217{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003218
3219
3220 const TagSpecification TagSpecText = {uTagRequirement,
3221 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3222 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3223 };
3224 const TagSpecification TagSpecBinary = {uTagRequirement,
3225 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3226 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3227 };
3228
3229
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003230 QCBORError uReturn;
3231
3232 if(CheckTagRequirement(TagSpecText, pItem->uDataType)) {
3233 *pMessage = pItem->val.string;
3234 if(pbIsNot7Bit != NULL) {
3235 *pbIsNot7Bit = false;
3236 }
3237 uReturn = QCBOR_SUCCESS;
3238 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType)) {
3239 *pMessage = pItem->val.string;
3240 if(pbIsNot7Bit != NULL) {
3241 *pbIsNot7Bit = true;
3242 }
3243 uReturn = QCBOR_SUCCESS;
3244
3245 } else {
3246 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3247 }
3248
3249 return uReturn;
3250}
3251
3252
3253
3254
3255
Laurence Lundbladec4537442020-04-14 18:53:22 -07003256
3257
3258
Laurence Lundbladee6430642020-03-14 21:15:44 -07003259
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003260typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003261
3262
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003263// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003264static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003265{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003266 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003267
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003268 if(uResult != 0) {
3269 /* This loop will run a maximum of 19 times because
3270 * UINT64_MAX < 10 ^^ 19. More than that will cause
3271 * exit with the overflow error
3272 */
3273 for(; nExponent > 0; nExponent--) {
3274 if(uResult > UINT64_MAX / 10) {
3275 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3276 }
3277 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003278 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003279
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003280 for(; nExponent < 0; nExponent++) {
3281 uResult = uResult / 10;
3282 if(uResult == 0) {
3283 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3284 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003285 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003286 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003287 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003288
3289 *puResult = uResult;
3290
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003291 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003292}
3293
3294
Laurence Lundbladee6430642020-03-14 21:15:44 -07003295/* Convert a decimal fraction to an int64_t without using
3296 floating point or math libraries. Most decimal fractions
3297 will not fit in an int64_t and this will error out with
3298 under or overflow
3299 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003300static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003301{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003302 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003303
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003304 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003305
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003306 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003307 * INT64_MAX < 2^31. More than that will cause
3308 * exist with the overflow error
3309 */
3310 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003311 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003312 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003313 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003314 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003315 nExponent--;
3316 }
3317
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003318 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003319 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003320 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3321 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003322 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003323 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003324 }
3325
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003326 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003327
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003328 return QCBOR_SUCCESS;
3329}
3330
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003331/*
3332 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3333 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003334static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3335{
3336 uint64_t uResult;
3337
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003338 // Take the absolute value of the mantissa and convert to unsigned.
3339 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003340 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3341
3342 // Do the exponentiation of the positive mantissa
3343 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3344 if(uReturn) {
3345 return uReturn;
3346 }
3347
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003348
Laurence Lundblade983500d2020-05-14 11:49:34 -07003349 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3350 of INT64_MIN. This assumes two's compliment representation where
3351 INT64_MIN is one increment farther from 0 than INT64_MAX.
3352 Trying to write -INT64_MIN doesn't work to get this because the
3353 compiler tries to work with an int64_t which can't represent
3354 -INT64_MIN.
3355 */
3356 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3357
3358 // Error out if too large
3359 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003360 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3361 }
3362
3363 // Casts are safe because of checks above
3364 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3365
3366 return QCBOR_SUCCESS;
3367}
3368
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003369/*
3370 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3371 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003372static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3373{
3374 if(nMantissa < 0) {
3375 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3376 }
3377
3378 // Cast to unsigned is OK because of check for negative
3379 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3380 // Exponentiation is straight forward
3381 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3382}
3383
3384
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003385#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003386
3387
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003388static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003389{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003390 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003391
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003392 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003393 const uint8_t *pByte = BigNum.ptr;
3394 size_t uLen = BigNum.len;
3395 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003396 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003397 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003398 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003399 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003400 }
3401
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003402 *pResult = uResult;
3403 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003404}
3405
Laurence Lundblade887add82020-05-17 05:50:34 -07003406static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003407{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003408 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003409}
3410
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003411static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003412{
3413 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003414 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3415 if(uError) {
3416 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003417 }
3418 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3419 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003420 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003421}
3422
3423
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003424static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003425{
3426 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003427 /* negaative int furthest from zero is INT64_MIN
3428 which is expressed as -INT64_MAX-1. The value of
3429 a negative bignum is -n-1, one further from zero
3430 than the positive bignum */
3431
3432 /* say INT64_MIN is -2; then INT64_MAX is 1.
3433 Then -n-1 <= INT64_MIN.
3434 Then -n -1 <= -INT64_MAX - 1
3435 THen n <= INT64_MAX. */
3436 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003437 if(uError) {
3438 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003439 }
3440 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003441 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003442 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003443 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003444 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003445}
3446
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003447#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003448
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003449
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003450/*
3451Convert a integers and floats to an int64_t.
3452
3453\param[in] uOptions Bit mask list of conversion options.
3454
3455\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3456
3457\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3458
3459\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3460
3461*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003462static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3463{
3464 switch(pItem->uDataType) {
3465 // TODO: float when ifdefs are set
3466 case QCBOR_TYPE_DOUBLE:
3467 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3468 // TODO: what about under/overflow here?
3469 // Invokes the floating-point HW and/or compiler-added libraries
3470 feclearexcept(FE_ALL_EXCEPT);
3471 *pnValue = llround(pItem->val.dfnum);
3472 if(fetestexcept(FE_INVALID)) {
3473 // TODO: better error code
3474 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3475 }
3476 } else {
3477 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3478 }
3479 break;
3480
3481 case QCBOR_TYPE_INT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003482 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003483 *pnValue = pItem->val.int64;
3484 } else {
3485 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3486 }
3487 break;
3488
3489 case QCBOR_TYPE_UINT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003490 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003491 if(pItem->val.uint64 < INT64_MAX) {
3492 *pnValue = pItem->val.int64;
3493 } else {
3494 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3495 }
3496 } else {
3497 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3498 }
3499 break;
3500
3501 default:
3502 return QCBOR_ERR_UNEXPECTED_TYPE;
3503 }
3504 return QCBOR_SUCCESS;
3505}
3506
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003507
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003508void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
3509 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003510 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003511 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003512{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003513 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003514 return;
3515 }
3516
Laurence Lundbladee6430642020-03-14 21:15:44 -07003517 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003518 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3519 if(uError) {
3520 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003521 return;
3522 }
3523
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003524 if(pItem) {
3525 *pItem = Item;
3526 }
3527
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003528 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003529}
3530
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003531
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003532void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3533 int64_t nLabel,
3534 uint32_t uOptions,
3535 int64_t *pnValue,
3536 QCBORItem *pItem)
3537{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003538 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003539 if(pMe->uLastError != QCBOR_SUCCESS) {
3540 return;
3541 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003542
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003543 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003544}
3545
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003546
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003547void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3548 const char * szLabel,
3549 uint32_t uOptions,
3550 int64_t *pnValue,
3551 QCBORItem *pItem)
3552{
3553 if(pMe->uLastError != QCBOR_SUCCESS) {
3554 return;
3555 }
3556
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003557 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003558 if(pMe->uLastError != QCBOR_SUCCESS) {
3559 return;
3560 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003561
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003562 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003563}
3564
3565
3566
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003567/*
3568 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003569
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003570 \param[in] uOptions Bit mask list of conversion options.
3571
3572 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3573
3574 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3575
3576 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3577
3578 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003579static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3580{
3581 QCBORError uErr;
3582
3583 switch(pItem->uDataType) {
3584
3585 case QCBOR_TYPE_POSBIGNUM:
3586 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3587 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003588 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003589 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003590 }
3591 break;
3592
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003593 case QCBOR_TYPE_NEGBIGNUM:
3594 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3595 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003596 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003597 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003598 }
3599 break;
3600
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003601#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3602 case QCBOR_TYPE_DECIMAL_FRACTION:
3603 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3604 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3605 pItem->val.expAndMantissa.nExponent,
3606 pnValue,
3607 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003608 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003609 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3610 }
3611 break;
3612
3613 case QCBOR_TYPE_BIGFLOAT:
3614 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3615 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3616 pItem->val.expAndMantissa.nExponent,
3617 pnValue,
3618 Exponentitate2);
3619 } else {
3620 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3621 }
3622 break;
3623
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003624 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3625 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3626 int64_t nMantissa;
3627 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3628 if(uErr) {
3629 return uErr;
3630 }
3631 return ExponentiateNN(nMantissa,
3632 pItem->val.expAndMantissa.nExponent,
3633 pnValue,
3634 Exponentitate10);
3635 } else {
3636 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3637 }
3638 break;
3639
3640 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3641 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3642 int64_t nMantissa;
3643 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3644 if(uErr) {
3645 return uErr;
3646 }
3647 return ExponentiateNN(nMantissa,
3648 pItem->val.expAndMantissa.nExponent,
3649 pnValue,
3650 Exponentitate10);
3651 } else {
3652 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3653 }
3654 break;
3655
3656 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3657 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3658 int64_t nMantissa;
3659 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3660 if(uErr) {
3661 return uErr;
3662 }
3663 return ExponentiateNN(nMantissa,
3664 pItem->val.expAndMantissa.nExponent,
3665 pnValue,
3666 Exponentitate2);
3667 } else {
3668 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3669 }
3670 break;
3671
3672 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3673 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3674 int64_t nMantissa;
3675 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3676 if(uErr) {
3677 return uErr;
3678 }
3679 return ExponentiateNN(nMantissa,
3680 pItem->val.expAndMantissa.nExponent,
3681 pnValue,
3682 Exponentitate2);
3683 } else {
3684 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003685 }
3686 break;
3687
Laurence Lundbladec4537442020-04-14 18:53:22 -07003688 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003689 return QCBOR_ERR_UNEXPECTED_TYPE;
3690#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07003691 }
3692}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003693
3694
Laurence Lundbladec4537442020-04-14 18:53:22 -07003695/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003696 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003697 */
3698void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003699{
3700 QCBORItem Item;
3701
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003702 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003703
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003704 if(pMe->uLastError == QCBOR_SUCCESS) {
3705 // The above conversion succeeded
3706 return;
3707 }
3708
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003709 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003710 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003711 return;
3712 }
3713
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003714 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003715}
3716
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003717
3718/*
3719Public function, see header qcbor/qcbor_decode.h file
3720*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003721void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
3722{
3723 QCBORItem Item;
3724
3725 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
3726
3727 if(pMe->uLastError == QCBOR_SUCCESS) {
3728 // The above conversion succeeded
3729 return;
3730 }
3731
3732 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3733 // The above conversion failed in a way that code below can't correct
3734 return;
3735 }
3736
3737 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3738}
3739
3740
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003741/*
3742Public function, see header qcbor/qcbor_decode.h file
3743*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003744void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3745{
3746 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003747 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3748
3749 if(pMe->uLastError == QCBOR_SUCCESS) {
3750 // The above conversion succeeded
3751 return;
3752 }
3753
3754 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3755 // The above conversion failed in a way that code below can't correct
3756 return;
3757 }
3758
3759 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3760}
3761
3762
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003763static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3764{
3765 switch(pItem->uDataType) {
3766 // TODO: type flaot
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003767 case QCBOR_CONVERT_TYPE_DOUBLE:
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003768 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3769 feclearexcept(FE_ALL_EXCEPT);
3770 double dRounded = round(pItem->val.dfnum);
3771 // TODO: over/underflow
3772 if(fetestexcept(FE_INVALID)) {
3773 // TODO: better error code
3774 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3775 } else if(isnan(dRounded)) {
3776 // TODO: better error code
3777 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3778 } else if(dRounded >= 0) {
3779 *puValue = (uint64_t)dRounded;
3780 } else {
3781 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3782 }
3783 } else {
3784 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3785 }
3786 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003787
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003788 case QCBOR_TYPE_INT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003789 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003790 if(pItem->val.int64 >= 0) {
3791 *puValue = (uint64_t)pItem->val.int64;
3792 } else {
3793 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3794 }
3795 } else {
3796 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3797 }
3798 break;
3799
3800 case QCBOR_TYPE_UINT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003801 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003802 *puValue = pItem->val.uint64;
3803 } else {
3804 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3805 }
3806 break;
3807
3808 default:
3809 return QCBOR_ERR_UNEXPECTED_TYPE;
3810 }
3811 return QCBOR_SUCCESS;
3812}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003813
3814
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003815void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3816 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003817 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003818 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003819{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003820 if(pMe->uLastError != QCBOR_SUCCESS) {
3821 return;
3822 }
3823
Laurence Lundbladec4537442020-04-14 18:53:22 -07003824 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003825
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003826 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3827 if(uError) {
3828 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003829 return;
3830 }
3831
Laurence Lundbladea826c502020-05-10 21:07:00 -07003832 if(pItem) {
3833 *pItem = Item;
3834 }
3835
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003836 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003837}
3838
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003839
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003840void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3841{
3842 int64_t uValue;
3843 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, &uValue, pItem);
3844 if(pMe->uLastError != QCBOR_SUCCESS) {
3845 return;
3846 }
3847
3848 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3849 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3850 }
3851}
3852
3853void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3854{
3855 int64_t uValue;
3856 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, &uValue, pItem);
3857 if(pMe->uLastError != QCBOR_SUCCESS) {
3858 return;
3859 }
3860
3861 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3862 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3863 }
3864}
3865
3866void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3867{
3868 int64_t uValue;
3869 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, &uValue, pItem);
3870 if(pMe->uLastError != QCBOR_SUCCESS) {
3871 return;
3872 }
3873
3874 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3875 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3876 }
3877}
3878
3879
3880
3881
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003882void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3883 int64_t nLabel,
3884 uint32_t uOptions,
3885 uint64_t *puValue,
3886 QCBORItem *pItem)
3887{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003888 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003889 if(pMe->uLastError != QCBOR_SUCCESS) {
3890 return;
3891 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003892
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003893 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uOptions, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003894}
3895
3896
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003897void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003898 const char * szLabel,
3899 uint32_t uOptions,
3900 uint64_t *puValue,
3901 QCBORItem *pItem)
3902{
3903 if(pMe->uLastError != QCBOR_SUCCESS) {
3904 return;
3905 }
3906
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003907 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003908 if(pMe->uLastError != QCBOR_SUCCESS) {
3909 return;
3910 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003911
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003912 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uOptions, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003913}
3914
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003915/*
3916 Public function, see header qcbor/qcbor_decode.h file
3917*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003918static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3919{
3920 QCBORError uErr;
3921
3922 switch(pItem->uDataType) {
3923
3924 case QCBOR_TYPE_POSBIGNUM:
3925 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3926 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3927 } else {
3928 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3929 }
3930 break;
3931
3932 case QCBOR_TYPE_NEGBIGNUM:
3933 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3934 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3935 } else {
3936 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3937 }
3938 break;
3939
3940#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3941
3942 case QCBOR_TYPE_DECIMAL_FRACTION:
3943 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3944 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3945 pItem->val.expAndMantissa.nExponent,
3946 puValue,
3947 Exponentitate10);
3948 } else {
3949 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3950 }
3951 break;
3952
3953 case QCBOR_TYPE_BIGFLOAT:
3954 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3955 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3956 pItem->val.expAndMantissa.nExponent,
3957 puValue,
3958 Exponentitate2);
3959 } else {
3960 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3961 }
3962 break;
3963
3964 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3965 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3966 // TODO: Would be better to convert to unsigned
3967 int64_t nMantissa;
3968 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3969 if(uErr != QCBOR_SUCCESS) {
3970 return uErr;
3971 }
3972 return ExponentitateNU(nMantissa,
3973 pItem->val.expAndMantissa.nExponent,
3974 puValue,
3975 Exponentitate10);
3976 } else {
3977 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3978 }
3979 break;
3980
3981 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3982 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3983 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3984 } else {
3985 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3986 }
3987 break;
3988
3989 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3990 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3991 // TODO: Would be better to convert to unsigned
3992 int64_t nMantissa;
3993 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3994 if(uErr != QCBOR_SUCCESS) {
3995 return uErr;
3996 }
3997 return ExponentitateNU(nMantissa,
3998 pItem->val.expAndMantissa.nExponent,
3999 puValue,
4000 Exponentitate2);
4001 } else {
4002 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4003 }
4004 break;
4005
4006 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4007 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4008 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4009 } else {
4010 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4011 }
4012 break;
4013#endif
4014 default:
4015 return QCBOR_ERR_UNEXPECTED_TYPE;
4016 }
4017}
4018
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004019/*
4020 Public function, see header qcbor/qcbor_decode.h file
4021*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004022void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004023{
4024 QCBORItem Item;
4025
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004026 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004027
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004028 if(pMe->uLastError == QCBOR_SUCCESS) {
4029 // The above conversion succeeded
4030 return;
4031 }
4032
4033 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4034 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004035 return;
4036 }
4037
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004038 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004039}
4040
Laurence Lundbladec4537442020-04-14 18:53:22 -07004041
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004042/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004043 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004044*/
4045void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
4046{
4047 QCBORItem Item;
4048
4049 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
4050
4051 if(pMe->uLastError == QCBOR_SUCCESS) {
4052 // The above conversion succeeded
4053 return;
4054 }
4055
4056 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4057 // The above conversion failed in a way that code below can't correct
4058 return;
4059 }
4060
4061 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4062}
4063
4064
4065/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004066 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004067*/
4068void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
4069{
4070 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004071 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004072
4073 if(pMe->uLastError == QCBOR_SUCCESS) {
4074 // The above conversion succeeded
4075 return;
4076 }
4077
4078 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4079 // The above conversion failed in a way that code below can't correct
4080 return;
4081 }
4082
4083 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4084}
4085
4086
4087static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
4088{
4089 switch(pItem->uDataType) {
4090 // TODO: float when ifdefs are set
4091 case QCBOR_TYPE_DOUBLE:
4092 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4093 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4094 *pdValue = pItem->val.dfnum;
4095 } else {
4096 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4097 }
4098 }
4099 break;
4100
4101 case QCBOR_TYPE_INT64:
4102 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
4103 // TODO: how does this work?
4104 *pdValue = (double)pItem->val.int64;
4105
4106 } else {
4107 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4108 }
4109 break;
4110
4111 case QCBOR_TYPE_UINT64:
4112 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
4113 *pdValue = (double)pItem->val.uint64;
4114 } else {
4115 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4116 }
4117 break;
4118
4119 default:
4120 return QCBOR_ERR_UNEXPECTED_TYPE;
4121 }
4122
4123 return QCBOR_SUCCESS;
4124}
4125
4126
4127
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004128void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
4129 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004130 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004131 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004132{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004133 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004134 return;
4135 }
4136
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004137 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004138
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004139 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004140 if(uError) {
4141 pMe->uLastError = (uint8_t)uError;
4142 return;
4143 }
4144
4145 if(pItem) {
4146 *pItem = Item;
4147 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004148
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004149 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004150}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004151
Laurence Lundbladec4537442020-04-14 18:53:22 -07004152
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004153void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4154 int64_t nLabel,
4155 uint32_t uOptions,
4156 double *pdValue,
4157 QCBORItem *pItem)
4158{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004159 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004160 if(pMe->uLastError != QCBOR_SUCCESS) {
4161 return;
4162 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004163
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004164 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uOptions, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004165}
4166
4167void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4168 const char * szLabel,
4169 uint32_t uOptions,
4170 double *pdValue,
4171 QCBORItem *pItem)
4172{
4173 if(pMe->uLastError != QCBOR_SUCCESS) {
4174 return;
4175 }
4176
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004177 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004178 if(pMe->uLastError != QCBOR_SUCCESS) {
4179 return;
4180 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004181
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004182 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uOptions, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004183}
4184
4185
4186
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004187static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4188{
4189 double dResult;
4190
4191 dResult = 0.0;
4192 const uint8_t *pByte = BigNum.ptr;
4193 size_t uLen = BigNum.len;
4194 /* This will overflow and become the float value INFINITY if the number
4195 is too large to fit. No error will be logged.
4196 TODO: should an error be logged? */
4197 while(uLen--) {
4198 dResult = (dResult * 256.0) + (double)*pByte++;
4199 }
4200
4201 return dResult;
4202}
4203
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004204static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004205{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004206 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004207 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4208
4209 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004210 switch(pItem->uDataType) {
4211 // TODO: type float
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004212
4213#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004214 case QCBOR_TYPE_DECIMAL_FRACTION:
4215 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4216 // TODO: rounding and overflow errors
4217 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4218 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4219 } else {
4220 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4221 }
4222 break;
4223
4224 case QCBOR_TYPE_BIGFLOAT:
4225 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
4226 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4227 exp2((double)pItem->val.expAndMantissa.nExponent);
4228 } else {
4229 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4230 }
4231 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004232#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004233
4234 case QCBOR_TYPE_POSBIGNUM:
4235 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
4236 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4237 } else {
4238 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4239 }
4240 break;
4241
4242 case QCBOR_TYPE_NEGBIGNUM:
4243 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004244 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004245 } else {
4246 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4247 }
4248 break;
4249
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004250#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004251 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4252 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4253 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4254 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4255 } else {
4256 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4257 }
4258 break;
4259
4260 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4261 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4262 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4263 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4264 } else {
4265 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4266 }
4267 break;
4268
4269 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4270 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
4271 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4272 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4273 } else {
4274 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4275 }
4276 break;
4277
4278 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4279 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004280 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004281 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4282 } else {
4283 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4284 }
4285 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004286#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4287
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004288
4289 default:
4290 return QCBOR_ERR_UNEXPECTED_TYPE;
4291 }
4292
4293 return QCBOR_SUCCESS;
4294}
4295
4296
4297/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004298 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004299*/
4300void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
4301{
4302
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004303 QCBORItem Item;
4304
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004305 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004306
4307 if(pMe->uLastError == QCBOR_SUCCESS) {
4308 // The above conversion succeeded
4309 return;
4310 }
4311
4312 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4313 // The above conversion failed in a way that code below can't correct
4314 return;
4315 }
4316
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004317 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004318}
4319
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004320
4321/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004322 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004323*/
4324void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
4325{
4326 QCBORItem Item;
4327
4328 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
4329
4330 if(pMe->uLastError == QCBOR_SUCCESS) {
4331 // The above conversion succeeded
4332 return;
4333 }
4334
4335 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4336 // The above conversion failed in a way that code below can't correct
4337 return;
4338 }
4339
4340 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4341}
4342
4343
4344/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004345 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004346*/
4347void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
4348{
4349 QCBORItem Item;
4350 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
4351
4352 if(pMe->uLastError == QCBOR_SUCCESS) {
4353 // The above conversion succeeded
4354 return;
4355 }
4356
4357 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4358 // The above conversion failed in a way that code below can't correct
4359 return;
4360 }
4361
4362 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4363}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004364
4365
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004366#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004367static void ProcessDecimalFraction(QCBORDecodeContext *pMe,
4368 uint8_t uTagRequirement,
4369 QCBORItem *pItem,
4370 int64_t *pnMantissa,
4371 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004372{
4373 QCBORError uErr;
4374
4375 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004376
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004377 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4378 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4379 return;
4380 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004381 /* The decimal fraction was untagged so it shows up as an
4382 array at this point. We are called to interpret it
4383 as a decimal fraction, so do protocol decoding. If
4384 it was tagged, iw would shouw up here with the
4385 QCBOR_TYPE_DECIMAL_FRACTION or such. */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004386 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4387 if(uErr != QCBOR_SUCCESS) {
4388 pMe->uLastError = (uint8_t)uErr;
4389 return;
4390 }
4391 }
4392
4393 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4394 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4395 return;
4396 }
4397
4398 switch (pItem->uDataType) {
4399
4400 case QCBOR_TYPE_DECIMAL_FRACTION:
4401 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4402 *pnExponent = pItem->val.expAndMantissa.nExponent;
4403 break;
4404
4405 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4406 *pnExponent = pItem->val.expAndMantissa.nExponent;
4407
4408 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4409 if(uErr != QCBOR_SUCCESS) {
4410 pMe->uLastError = (uint8_t)uErr;
4411 }
4412 break;
4413
4414 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4415 *pnExponent = pItem->val.expAndMantissa.nExponent;
4416
4417 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4418 if(uErr != QCBOR_SUCCESS) {
4419 pMe->uLastError = (uint8_t)uErr;
4420 }
4421 break;
4422
4423 default:
4424 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4425 }
4426}
4427
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004428
4429void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
4430 uint8_t uTagRequirement,
4431 int64_t *pnMantissa,
4432 int64_t *pnExponent)
4433{
4434 if(pMe->uLastError != QCBOR_SUCCESS) {
4435 return;
4436 }
4437
4438 QCBORItem Item;
4439 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4440 if(uError) {
4441 pMe->uLastError = (uint8_t)uError;
4442 return;
4443 }
4444
4445 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4446}
4447
4448
4449void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004450 uint8_t uTagRequirement,
4451 int64_t nLabel,
4452 int64_t *pnMantissa,
4453 int64_t *pnExponent)
4454{
4455 QCBORItem Item;
4456
4457 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004458 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004459}
4460
4461
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004462void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
4463 uint8_t uTagRequirement,
4464 const char *szLabel,
4465 int64_t *pnMantissa,
4466 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004467{
4468 QCBORItem Item;
4469
4470 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4471
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004472 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004473}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004474#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004475
4476
4477UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4478{
4479 while(uInt & 0xff0000000000UL) {
4480 uInt = uInt << 8;
4481 };
4482
4483 UsefulOutBuf UOB;
4484
4485 UsefulOutBuf_Init(&UOB, Buffer);
4486
4487 while(uInt) {
4488 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56));
4489 uInt = uInt << 8;
4490 }
4491
4492 return UsefulOutBuf_OutUBuf(&UOB);
4493}
4494
4495
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004496#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4497
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004498static void ProcessDecimalFractionBig(QCBORDecodeContext *pMe,
4499 uint8_t uTagRequirement,
4500 QCBORItem *pItem,
4501 UsefulBuf BufferForMantissa,
4502 UsefulBufC *pMantissa,
4503 bool *pbIsNegative,
4504 int64_t *pnExponent)
4505{
4506
4507 const TagSpecification TagSpec = {uTagRequirement,
4508 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4509 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4510 };
4511
4512 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
4513 if(uErr != QCBOR_SUCCESS) {
4514 pMe->uLastError = (uint8_t)uErr;
4515 return;
4516 }
4517
4518 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
4519 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4520 if(uErr != QCBOR_SUCCESS) {
4521 pMe->uLastError = (uint8_t)uErr;
4522 return;
4523 }
4524 }
4525
4526 uint64_t uMantissa;
4527
4528 switch (pItem->uDataType) {
4529
4530 case QCBOR_TYPE_DECIMAL_FRACTION:
4531 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
4532 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
4533 *pbIsNegative = false;
4534 } else {
4535 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
4536 *pbIsNegative = true;
4537 }
4538 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
4539 *pnExponent = pItem->val.expAndMantissa.nExponent;
4540 break;
4541
4542 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4543 *pnExponent = pItem->val.expAndMantissa.nExponent;
4544 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4545 *pbIsNegative = false;
4546 break;
4547
4548 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4549 *pnExponent = pItem->val.expAndMantissa.nExponent;
4550 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4551 *pbIsNegative = true;
4552 break;
4553
4554 default:
4555 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4556 }
4557}
4558
4559
4560void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
4561 uint8_t uTagRequirement,
4562 UsefulBuf MantissaBuffer,
4563 UsefulBufC *pMantissa,
4564 bool *pbMantissaIsNegative,
4565 int64_t *pnExponent)
4566{
4567
4568 if(pMe->uLastError != QCBOR_SUCCESS) {
4569 return;
4570 }
4571
4572 QCBORItem Item;
4573 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4574 if(uError) {
4575 pMe->uLastError = (uint8_t)uError;
4576 return;
4577 }
4578
4579 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
4580
4581}
4582
4583void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
4584 uint8_t uTagRequirement,
4585 int64_t nLabel,
4586 UsefulBuf BufferForMantissa,
4587 UsefulBufC *pMantissa,
4588 bool *pbIsNegative,
4589 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004590{
4591 QCBORItem Item;
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004592
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004593 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004594 if(pMe->uLastError != QCBOR_SUCCESS) {
4595 return;
4596 }
4597
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004598 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
4599}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004600
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004601
4602void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
4603 uint8_t uTagRequirement,
4604 const char *szLabel,
4605 UsefulBuf BufferForMantissa,
4606 UsefulBufC *pMantissa,
4607 bool *pbIsNegative,
4608 int64_t *pnExponent)
4609{
4610 QCBORItem Item;
4611
4612 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4613 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004614 return;
4615 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004616
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004617 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004618}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004619
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004620#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004621
4622/*
4623
4624 TODO: do something with this text
4625 The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...)
4626 formed by intermediate nodes (arrays and maps). The cursor for the traversal
4627 is the byte offset in the encoded input and a leaf counter for definite
4628 length maps and arrays. Indefinite length maps and arrays are handled
4629 by look ahead for the break.
4630
4631 The view presented to the caller has tags, labels and the chunks of
4632 indefinite length strings aggregated into one decorated data item.
4633
4634 The caller understands the nesting level in pre-order traversal by
4635 the fact that a data item that is a map or array is presented to
4636 the caller when it is first encountered in the pre-order traversal and that all data items are presented with its nesting level
4637 and the nesting level of the next item.
4638
4639 The caller traverse maps and arrays in a special mode that often more convenient
4640 that tracking by nesting level. When an array or map is expected or encountered
4641 the EnterMap or EnteryArray can be called.
4642
4643 When entering a map or array like this, the cursor points to the first
4644 item in the map or array. When exiting, it points to the item after
4645 the map or array, regardless of whether the items in the map or array were
4646 all traversed.
4647
4648 When in a map or array, the cursor functions as normal, but traversal
4649 cannot go past the end of the map or array that was entered. If this
4650 is attempted the QCBOR_ERR_NO_MORE_ITEMS error is returned. To
4651 go past the end of the map or array ExitMap() or ExitArray() must
4652 be called. It can be called any time regardless of the position
4653 of the cursor.
4654
4655 When a map is entered, a special function allows fetching data items
4656 by label. This call will traversal the whole map looking for the
4657 labeled item. The whole map is traversed so as to detect duplicates.
4658 This type of fetching items does not affect the normal traversal
4659 cursor.
4660
4661
4662 When a data item is presented to the caller, the nesting level of the data
4663 item is presented along with the nesting level of the item that would be
4664 next consumed.
4665 */