blob: 6f60ef67d7bfe0f7aba38f3fc8db80973d254c5e [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 Lundblade085d7952020-07-24 10:26:30 -0700127static inline bool
128DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
129{
130 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
131 return true;
132 } else {
133 return false;
134 }
135}
136
137
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700138inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700139DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700140{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700141 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700142 return true;
143 } else {
144 return false;
145 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700146}
147
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700148
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700149inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700150DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700151{
152 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700153 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700154 return false;
155 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700156 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700157 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700158 return false;
159 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700160 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700161 return true;
162}
163
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700164
Laurence Lundblade642282a2020-06-23 12:00:33 -0700165inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700166DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700167{
168 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700169 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700170 return true;
171 }
172 return false;
173}
174
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700175
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700176inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700177{
178 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
179 return true;
180 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700181 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700182 return true;
183 }
184 return false;
185}
186
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700187
Laurence Lundblade085d7952020-07-24 10:26:30 -0700188inline static void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700189{
190 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700191 /*
192 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
193 larger than DecodeNesting_EnterBoundedMode which keeps it less than
194 uin32_t so the cast is safe.
195 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700196 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700197
198 if(bIsEmpty) {
199 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
200 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700201}
202
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700203
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700204inline static void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700205{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700206 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700207}
208
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700209
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700210inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700211DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700212{
213 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700214 // No bounded map or array or... set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700215 return false;
216 }
217 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700218 // Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700219 return false;
220 }
221 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700222 // Not at a bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700223 return false;
224 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700225 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700226 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700227 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700228 return false;
229 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700230 // All checks passed, got to the end of a map/array
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700231 return true;
232}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700233
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700234
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700235inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700236DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700237{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700238 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700239 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
240 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700241 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700242 return false;
243 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700244}
245
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700246
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700247inline static bool
248DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700249{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700250 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
251 return true;
252 } else {
253 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700254 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700255}
256
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700257
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700258inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700259DecodeNesting_CheckBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700260{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700261 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700262 return false;
263 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700264
265 if(pNesting->pCurrentBounded->uLevelType != uType) {
266 return false;
267 }
268
269 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700270}
271
Laurence Lundblade02625d42020-06-25 14:41:41 -0700272
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700273inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700274DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700275{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700276 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700277 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700278}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700279
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700280
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700281inline static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700282DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
283{
284 // Only call on a defnite length array / map
285 pNesting->pCurrent->u.ma.uCountCursor++;
286}
287
288
289inline static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700290DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
291{
292 pNesting->pCurrent--;
293}
294
Laurence Lundblade02625d42020-06-25 14:41:41 -0700295
296static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700297DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700298{
299 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700300 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700301 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
302 }
303
304 // The actual descend
305 pNesting->pCurrent++;
306
307 pNesting->pCurrent->uLevelType = uType;
308
309 return QCBOR_SUCCESS;
310}
311
312
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700313inline static QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700314DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700315{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700316 /*
317 Should only be called on map/array.
318
319 Have descended into this before this is called. The job here is
320 just to mark it in bounded mode.
321 */
Laurence Lundblade085d7952020-07-24 10:26:30 -0700322 if(uOffset >= QCBOR_NON_BOUNDED_OFFSET) { //TODO: fix this bounds check
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700323 return QCBOR_ERR_BUFFER_TOO_LARGE;
324 }
325
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700326 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700327
328 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700329
330 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700331}
332
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700333
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700334inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700335DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700336 uint8_t uQCBORType,
337 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700338{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700339 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700340
341 if(uCount == 0) {
342 // Nothing to do for empty definite lenth arrays. They are just are
343 // effectively the same as an item that is not a map or array
344 goto Done;
345 // Empty indefinite length maps and arrays are handled elsewhere
346 }
347
348 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700349 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
350 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
351 uError = QCBOR_ERR_ARRAY_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700352 goto Done;
353 }
354
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700355 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700356 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700357 goto Done;
358 }
359
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700360 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700361 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
362 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700363
364 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700365
366Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700367 return uError;;
368}
369
370
371static inline void
372DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
373{
374 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
375}
376
377
378static inline void
379DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
380{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700381 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700382 pNesting->pCurrentBounded--;
383 if(DecodeNesting_IsCurrentBounded(pNesting)) {
384 break;
385 }
386 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700387}
388
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700389static inline void
390DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
391{
392 pNesting->pCurrent = pNesting->pCurrentBounded;
393}
394
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700395
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700396inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700397DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
398 size_t uEndOffset,
399 size_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700400{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700401 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700402
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700403 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700404 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700405 goto Done;
406 }
407
Laurence Lundblade02625d42020-06-25 14:41:41 -0700408 // Fill in the new byte string level
409 // TODO: justify cast
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700410 pNesting->pCurrent->u.bs.uPreviousEndOffset = (uint32_t)uEndOffset;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700411 pNesting->pCurrent->u.bs.uEndOfBstr = (uint32_t)uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700412
Laurence Lundblade02625d42020-06-25 14:41:41 -0700413 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700414 pNesting->pCurrentBounded = pNesting->pCurrent;
415
416Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700417 return uError;;
418}
419
Laurence Lundbladed0304932020-06-27 10:59:38 -0700420
421static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700422DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700423{
424 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700425}
426
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700427
Laurence Lundbladeee851742020-01-08 08:37:05 -0800428inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700429DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700430{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700431 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700432 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
433 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700434}
435
436
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700437inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700438DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700439{
Laurence Lundblade085d7952020-07-24 10:26:30 -0700440 //*pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700441 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700442 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700443}
444
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700445
Laurence Lundblade02625d42020-06-25 14:41:41 -0700446static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700447DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700448{
449 *pNesting = *pSave;
450}
451
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700452
Laurence Lundblade02625d42020-06-25 14:41:41 -0700453static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700454DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700455{
456 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
457}
458
459
Laurence Lundblade02625d42020-06-25 14:41:41 -0700460static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700461DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700462{
463 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
464}
465
466
Laurence Lundblade02625d42020-06-25 14:41:41 -0700467#include <stdio.h>
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700468
469const char *TypeStr(uint8_t type)
470{
471 switch(type) {
472 case QCBOR_TYPE_MAP: return " map";
473 case QCBOR_TYPE_ARRAY: return "array";
474 case QCBOR_TYPE_BYTE_STRING: return " bstr";
475 default: return " --- ";
476 }
477}
478
479static char buf[20]; // Not thread safe, but that is OK
480const char *CountString(uint16_t uCount, uint16_t uTotal)
481{
482 if(uTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
483 strcpy(buf, "indefinite");
484 } else {
485 sprintf(buf, "%d/%d", uCount, uTotal);
486 }
487 return buf;
488}
489
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700490
Laurence Lundblade02625d42020-06-25 14:41:41 -0700491void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700492{
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700493#if 0
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700494 printf("---%s--%d/%d--\narrow is current bounded level\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700495 szName,
496 (uint32_t)pBuf->cursor,
497 (uint32_t)pBuf->UB.len);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700498
499 printf("Level Type Count Offsets \n");
Laurence Lundblade02625d42020-06-25 14:41:41 -0700500 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700501 if(&(pNesting->pLevels[i]) > pNesting->pCurrent) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700502 break;
503 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700504
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700505 printf("%2s %2d %s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700506 pNesting->pCurrentBounded == &(pNesting->pLevels[i]) ? "->": " ",
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700507 i,
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700508 TypeStr(pNesting->pLevels[i].uLevelType));
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700509
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700510 if(pNesting->pLevels[i].uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700511 printf(" %5d %5d",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700512 pNesting->pLevels[i].u.bs.uEndOfBstr,
513 pNesting->pLevels[i].u.bs.uPreviousEndOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700514
515 } else {
516 printf("%10.10s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700517 CountString(pNesting->pLevels[i].u.ma.uCountCursor,
518 pNesting->pLevels[i].u.ma.uCountTotal));
519 if(pNesting->pLevels[i].u.ma.uStartOffset != UINT32_MAX) {
520 printf("Bounded start: %u",pNesting->pLevels[i].u.ma.uStartOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700521 }
522 }
523
524 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700525 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700526 printf("\n");
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700527#endif
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700528}
529
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700530
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700531
Laurence Lundbladeee851742020-01-08 08:37:05 -0800532/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800533 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
534
535 The following four functions are pretty wrappers for invocation of
536 the string allocator supplied by the caller.
537
Laurence Lundbladeee851742020-01-08 08:37:05 -0800538 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800539
Laurence Lundbladeee851742020-01-08 08:37:05 -0800540static inline void
541StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800542{
543 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
544}
545
Laurence Lundbladeee851742020-01-08 08:37:05 -0800546// StringAllocator_Reallocate called with pMem NULL is
547// equal to StringAllocator_Allocate()
548static inline UsefulBuf
549StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
550 void *pMem,
551 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800552{
553 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
554}
555
Laurence Lundbladeee851742020-01-08 08:37:05 -0800556static inline UsefulBuf
557StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800558{
559 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
560}
561
Laurence Lundbladeee851742020-01-08 08:37:05 -0800562static inline void
563StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800564{
565 if(pMe->pfAllocator) {
566 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
567 }
568}
569
570
571
Laurence Lundbladeee851742020-01-08 08:37:05 -0800572/*===========================================================================
573 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700574
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800575 See qcbor/qcbor_decode.h for definition of the object
576 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800577 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700578/*
579 Public function, see header file
580 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800581void QCBORDecode_Init(QCBORDecodeContext *me,
582 UsefulBufC EncodedCBOR,
583 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700584{
585 memset(me, 0, sizeof(QCBORDecodeContext));
586 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800587 // Don't bother with error check on decode mode. If a bad value is
588 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700589 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700590 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700591 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700592 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700593 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700594}
595
596
597/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700598 Public function, see header file
599 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800600void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
601 QCBORStringAllocate pfAllocateFunction,
602 void *pAllocateContext,
603 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700604{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800605 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
606 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
607 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700608}
609
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800610
611/*
612 Public function, see header file
613 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700614void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800615 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700616{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700617 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700618 (void)pMe;
619 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700620}
621
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700622
623/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800624 This decodes the fundamental part of a CBOR data item, the type and
625 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800626
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700627 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800628
Laurence Lundbladeee851742020-01-08 08:37:05 -0800629 This does the network->host byte order conversion. The conversion
630 here also results in the conversion for floats in addition to that
631 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800632
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700633 This returns:
634 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800635
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800636 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800637 tags and floats and length for strings and arrays
638
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800639 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800640 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800641
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800642 The int type is preferred to uint8_t for some variables as this
643 avoids integer promotions, can reduce code size and makes
644 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700645 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800646inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
647 int *pnMajorType,
648 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800649 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700650{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700651 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800652
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700653 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800654 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800655
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700656 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800657 const int nTmpMajorType = nInitialByte >> 5;
658 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800659
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800660 // Where the number or argument accumulates
661 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800662
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800663 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700664 // Need to get 1,2,4 or 8 additional argument bytes. Map
665 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800666 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800667
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800668 // Loop getting all the bytes in the argument
669 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800670 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800671 // This shift and add gives the endian conversion
672 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
673 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800674 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800675 // The reserved and thus-far unused additional info values
676 nReturn = QCBOR_ERR_UNSUPPORTED;
677 goto Done;
678 } else {
679 // Less than 24, additional info is argument or 31, an indefinite length
680 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800681 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700682 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800683
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700684 if(UsefulInputBuf_GetError(pUInBuf)) {
685 nReturn = QCBOR_ERR_HIT_END;
686 goto Done;
687 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800688
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700689 // All successful if we got here.
690 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800691 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800692 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800693 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800694
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700695Done:
696 return nReturn;
697}
698
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800699
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700700/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800701 CBOR doesn't explicitly specify two's compliment for integers but all
702 CPUs use it these days and the test vectors in the RFC are so. All
703 integers in the CBOR structure are positive and the major type
704 indicates positive or negative. CBOR can express positive integers
705 up to 2^x - 1 where x is the number of bits and negative integers
706 down to 2^x. Note that negative numbers can be one more away from
707 zero than positive. Stdint, as far as I can tell, uses two's
708 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800709
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700710 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800711 used carefully here, and in particular why it isn't used in the interface.
712 Also see
713 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
714
715 Int is used for values that need less than 16-bits and would be subject
716 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700717 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800718inline static QCBORError
719DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700720{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700721 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800722
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700723 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
724 if (uNumber <= INT64_MAX) {
725 pDecodedItem->val.int64 = (int64_t)uNumber;
726 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800727
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700728 } else {
729 pDecodedItem->val.uint64 = uNumber;
730 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800731
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732 }
733 } else {
734 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800735 // CBOR's representation of negative numbers lines up with the
736 // two-compliment representation. A negative integer has one
737 // more in range than a positive integer. INT64_MIN is
738 // equal to (-INT64_MAX) - 1.
739 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700740 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800741
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742 } else {
743 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000744 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700745 nReturn = QCBOR_ERR_INT_OVERFLOW;
746 }
747 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800748
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700749 return nReturn;
750}
751
752// Make sure #define value line up as DecodeSimple counts on this.
753#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
754#error QCBOR_TYPE_FALSE macro value wrong
755#endif
756
757#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
758#error QCBOR_TYPE_TRUE macro value wrong
759#endif
760
761#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
762#error QCBOR_TYPE_NULL macro value wrong
763#endif
764
765#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
766#error QCBOR_TYPE_UNDEF macro value wrong
767#endif
768
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700769#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
770#error QCBOR_TYPE_BREAK macro value wrong
771#endif
772
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700773#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
774#error QCBOR_TYPE_DOUBLE macro value wrong
775#endif
776
777#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
778#error QCBOR_TYPE_FLOAT macro value wrong
779#endif
780
781/*
782 Decode true, false, floats, break...
783 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800784inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800785DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700786{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700787 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800788
Laurence Lundbladeee851742020-01-08 08:37:05 -0800789 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800790 // above make sure uAdditionalInfo values line up with uDataType values.
791 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
792 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800793
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800794 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800795 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
796 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800797
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700798 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700799 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
800 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700801 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700802 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700803 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
804 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700805 break;
806 case DOUBLE_PREC_FLOAT:
807 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700808 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700809 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800810
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700811 case CBOR_SIMPLEV_FALSE: // 20
812 case CBOR_SIMPLEV_TRUE: // 21
813 case CBOR_SIMPLEV_NULL: // 22
814 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700815 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700816 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800817
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700818 case CBOR_SIMPLEV_ONEBYTE: // 24
819 if(uNumber <= CBOR_SIMPLE_BREAK) {
820 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700821 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700822 goto Done;
823 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800824 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700825 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800826
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700827 default: // 0-19
828 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800829 /*
830 DecodeTypeAndNumber will make uNumber equal to
831 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
832 safe because the 2, 4 and 8 byte lengths of uNumber are in
833 the double/float cases above
834 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700835 pDecodedItem->val.uSimple = (uint8_t)uNumber;
836 break;
837 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800838
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700839Done:
840 return nReturn;
841}
842
843
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700844/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530845 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700846 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800847inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
848 int nMajorType,
849 uint64_t uStrLen,
850 UsefulInputBuf *pUInBuf,
851 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700852{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700853 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800854
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800855 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
856 // This check makes the casts to size_t below safe.
857
858 // 4 bytes less than the largest sizeof() so this can be tested by
859 // putting a SIZE_MAX length in the CBOR test input (no one will
860 // care the limit on strings is 4 bytes shorter).
861 if(uStrLen > SIZE_MAX-4) {
862 nReturn = QCBOR_ERR_STRING_TOO_LONG;
863 goto Done;
864 }
865
866 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530867 if(UsefulBuf_IsNULLC(Bytes)) {
868 // Failed to get the bytes for this string item
869 nReturn = QCBOR_ERR_HIT_END;
870 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700871 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530872
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800873 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530874 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800875 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530876 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700877 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530878 goto Done;
879 }
880 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800881 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530882 } else {
883 // Normal case with no string allocator
884 pDecodedItem->val.string = Bytes;
885 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800886 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800887 // Cast because ternary operator causes promotion to integer
888 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
889 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800890
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530891Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700892 return nReturn;
893}
894
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700895
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800896
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700897
898
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700899
900
Laurence Lundbladeee851742020-01-08 08:37:05 -0800901// Make sure the constants align as this is assumed by
902// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700903#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
904#error QCBOR_TYPE_ARRAY value not lined up with major type
905#endif
906#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
907#error QCBOR_TYPE_MAP value not lined up with major type
908#endif
909
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700910/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800911 This gets a single data item and decodes it including preceding
912 optional tagging. This does not deal with arrays and maps and nesting
913 except to decode the data item introducing them. Arrays and maps are
914 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800915
Laurence Lundbladeee851742020-01-08 08:37:05 -0800916 Errors detected here include: an array that is too long to decode,
917 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700918 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800919static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
920 QCBORItem *pDecodedItem,
921 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700922{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700923 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800924
Laurence Lundbladeee851742020-01-08 08:37:05 -0800925 /*
926 Get the major type and the number. Number could be length of more
927 bytes or the value depending on the major type nAdditionalInfo is
928 an encoding of the length of the uNumber and is needed to decode
929 floats and doubles
930 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800931 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700932 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800933 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800934
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700935 memset(pDecodedItem, 0, sizeof(QCBORItem));
936
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800937 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800938
Laurence Lundbladeee851742020-01-08 08:37:05 -0800939 // Error out here if we got into trouble on the type and number. The
940 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700941 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700942 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700943 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800944
Laurence Lundbladeee851742020-01-08 08:37:05 -0800945 // At this point the major type and the value are valid. We've got
946 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800947 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700948 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
949 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800950 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700951 nReturn = QCBOR_ERR_BAD_INT;
952 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800953 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700954 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700955 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800956
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700957 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
958 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800959 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
960 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
961 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
962 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530963 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700964 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800965 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700966 }
967 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800968
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700969 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
970 case CBOR_MAJOR_TYPE_MAP: // Major type 5
971 // Record the number of items in the array or map
972 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
973 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
974 goto Done;
975 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800976 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700977 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700978 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800979 // type conversion OK because of check above
980 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800982 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800983 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
984 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700985 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800986
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700987 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800988 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700989 nReturn = QCBOR_ERR_BAD_INT;
990 } else {
991 pDecodedItem->val.uTagV = uNumber;
992 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
993 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700994 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800995
Laurence Lundbladeee851742020-01-08 08:37:05 -0800996 case CBOR_MAJOR_TYPE_SIMPLE:
997 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800998 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700999 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001000
Laurence Lundbladeee851742020-01-08 08:37:05 -08001001 default:
1002 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001003 nReturn = QCBOR_ERR_UNSUPPORTED;
1004 break;
1005 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001006
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001007Done:
1008 return nReturn;
1009}
1010
1011
1012
1013/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001014 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001015 individual chunk items together into one QCBORItem using the string
1016 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001017
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301018 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001019 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001020static inline QCBORError
1021GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001022{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001023 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001024
1025 // Get pointer to string allocator. First use is to pass it to
1026 // GetNext_Item() when option is set to allocate for *every* string.
1027 // Second use here is to allocate space to coallese indefinite
1028 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001029 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1030 &(me->StringAllocator) :
1031 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001032
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001033 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001034 nReturn = GetNext_Item(&(me->InBuf),
1035 pDecodedItem,
1036 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001037 if(nReturn) {
1038 goto Done;
1039 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001040
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001041 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301042 // code in this function from here down can be eliminated. Run tests, except
1043 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001044
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001045 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001046 const uint8_t uStringType = pDecodedItem->uDataType;
1047 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001048 goto Done; // no need to do any work here on non-string types
1049 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001050
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001051 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301052 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001053 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001054 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001055
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301056 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001057 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001058 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1059 goto Done;
1060 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001061
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001062 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001063 UsefulBufC FullString = NULLUsefulBufC;
1064
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001065 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001066 // Get item for next chunk
1067 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001068 // NULL string allocator passed here. Do not need to allocate
1069 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001070 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001071 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001072 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001073 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001074
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301075 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001076 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001077 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001078 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301079 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001080 break;
1081 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001082
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001083 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301084 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001085 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001086 if(StringChunkItem.uDataType != uStringType ||
1087 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001088 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001089 break;
1090 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001091
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301092 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001093 // The first time throurgh FullString.ptr is NULL and this is
1094 // equivalent to StringAllocator_Allocate()
1095 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1096 UNCONST_POINTER(FullString.ptr),
1097 FullString.len + StringChunkItem.val.string.len);
1098
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001099 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301100 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001101 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001102 break;
1103 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001104
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001105 // Copy new string chunk at the end of string so far.
1106 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001107 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001108
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001109 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1110 // Getting the item failed, clean up the allocated memory
1111 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001112 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001113
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001114Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001115 return nReturn;
1116}
1117
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001118
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001119static uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1120 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001121 return uTagVal;
1122 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001123 int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001124 return me->auMappedTags[x];
1125 }
1126}
1127
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001128/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001129 Gets all optional tag data items preceding a data item that is not an
1130 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001131 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001132static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001133GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001134{
Laurence Lundblade30816f22018-11-10 13:40:22 +07001135 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001136
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001137 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1138 CBOR_TAG_INVALID16,
1139 CBOR_TAG_INVALID16,
1140 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001141
Laurence Lundblade59289e52019-12-30 13:44:37 -08001142 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001143 for(;;) {
1144 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001145 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001146 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001147 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001148
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001149 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1150 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001151 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001152 break;
1153 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001154
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001155 // Is there room for the tag in the tags list?
1156 size_t uTagIndex;
1157 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001158 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001159 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001160 }
1161 }
1162 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001163 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001164 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001165
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001166 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001167 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001168 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001169 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001170 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001171 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001172 break;
1173 }
1174 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001175 // TODO: test this
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001176 break;
1177 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001178 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001179 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1180 // No room for the tag
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001181 // Should never happen as long as QCBOR_MAX_TAGS_PER_ITEM <= QCBOR_NUM_MAPPED_TAGS
1182 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001183 }
1184
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001185 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001186 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001187 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001188
1189 } else {
1190 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001191 }
1192 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001193
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001194Done:
1195 return nReturn;
1196}
1197
1198
1199/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001200 This layer takes care of map entries. It combines the label and data
1201 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001202 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001203static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001204GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001205{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001206 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001207 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001208 if(nReturn)
1209 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001210
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001211 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001212 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001213 goto Done;
1214 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001215
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001216 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1217 // In a map and caller wants maps decoded, not treated as arrays
1218
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001219 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001220 // If in a map and the right decoding mode, get the label
1221
Laurence Lundbladeee851742020-01-08 08:37:05 -08001222 // Save label in pDecodedItem and get the next which will
1223 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001224 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001225 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001226 if(nReturn)
1227 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001228
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301229 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001230
1231 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1232 // strings are always good labels
1233 pDecodedItem->label.string = LabelItem.val.string;
1234 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1235 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001236 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001237 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1238 goto Done;
1239 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1240 pDecodedItem->label.int64 = LabelItem.val.int64;
1241 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1242 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1243 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1244 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1245 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1246 pDecodedItem->label.string = LabelItem.val.string;
1247 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1248 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1249 } else {
1250 // label is not an int or a string. It is an arrray
1251 // or a float or such and this implementation doesn't handle that.
1252 // Also, tags on labels are ignored.
1253 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1254 goto Done;
1255 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001256 }
1257 } else {
1258 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001259 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1260 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1261 goto Done;
1262 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001263 // Decoding a map as an array
1264 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001265 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1266 // Cast is needed because of integer promotion
1267 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001268 }
1269 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001270
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001271Done:
1272 return nReturn;
1273}
1274
1275
Laurence Lundblade02625d42020-06-25 14:41:41 -07001276/*
1277 See if next item is a CBOR break. If it is, it is consumed,
1278 if not it is not consumed.
1279*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001280static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001281NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1282{
1283 *pbNextIsBreak = false;
1284 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001285 QCBORItem Peek;
1286 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1287 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1288 if(uReturn != QCBOR_SUCCESS) {
1289 return uReturn;
1290 }
1291 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001292 // It is not a break, rewind so it can be processed normally.
1293 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001294 } else {
1295 *pbNextIsBreak = true;
1296 }
1297 }
1298
1299 return QCBOR_SUCCESS;
1300}
1301
1302
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001303/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001304 An item was just consumed, now figure out if it was the
1305 end of an array or map that can be closed out. That
1306 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001307*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001308static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001309{
1310 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001311
Laurence Lundblade642282a2020-06-23 12:00:33 -07001312 /* This loops ascending nesting levels as long as there is ascending to do */
1313 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1314
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001315 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001316 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001317 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1318 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001319 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001320 break;
1321 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001322 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001323
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001324 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001325 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001326 bool bIsBreak = false;
1327 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1328 if(uReturn != QCBOR_SUCCESS) {
1329 goto Done;
1330 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001331
1332 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001333 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001334 break;
1335 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001336
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001337 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001338 /*
1339 Break occurred inside a bstr-wrapped CBOR or
1340 in the top level sequence. This is always an
1341 error because neither are an indefinte length
1342 map/array.
1343 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001344 uReturn = QCBOR_ERR_BAD_BREAK;
1345 goto Done;
1346 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001347 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001348 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001349
Laurence Lundblade02625d42020-06-25 14:41:41 -07001350 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001351
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001352 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001353 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001354 /* 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 -07001355 if(bMarkEnd) {
1356 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001357 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001358
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001359 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001360 break;
1361 }
1362
1363 /* Finally, actually ascend one level. */
1364 DecodeNesting_Ascend(&(pMe->nesting));
1365 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001366
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001367 uReturn = QCBOR_SUCCESS;
1368
1369Done:
1370 return uReturn;
1371}
1372
1373
1374/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001375 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001376 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1377 indefinte length maps and arrays by looking at the item count or
1378 finding CBOR breaks. It detects the ends of the top-level sequence
1379 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001380 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001381static QCBORError
1382QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001383{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001384 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001385 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001386
Laurence Lundblade642282a2020-06-23 12:00:33 -07001387 /*
1388 If out of bytes to consume, it is either the end of the top-level
1389 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001390
Laurence Lundblade642282a2020-06-23 12:00:33 -07001391 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1392 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1393 CBOR is exited, the length is set back to the top-level's length
1394 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001395 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001396 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001397 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001398 goto Done;
1399 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001400
Laurence Lundblade642282a2020-06-23 12:00:33 -07001401 /*
1402 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001403 array. The check for the end of an indefinite length array is
1404 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001405 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001406 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001407 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001408 goto Done;
1409 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001410
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001411 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001412 uReturn = GetNext_MapEntry(me, pDecodedItem);
1413 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001414 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001415 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301416
Laurence Lundblade642282a2020-06-23 12:00:33 -07001417 /*
1418 Breaks ending arrays/maps are always processed at the end of this
1419 function. They should never show up here.
1420 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301421 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001422 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301423 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301424 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001425
Laurence Lundblade642282a2020-06-23 12:00:33 -07001426 /*
1427 Record the nesting level for this data item before processing any
1428 of decrementing and descending.
1429 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001430 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001431
Laurence Lundblade642282a2020-06-23 12:00:33 -07001432
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001433 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001434 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001435 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001436 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001437
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001438 Empty indefinite length maps and arrays are descended into, but then ascended out
Laurence Lundblade02625d42020-06-25 14:41:41 -07001439 of in the next chunk of code.
1440
1441 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001442 encloses them so a decrement needs to be done for them too, but
1443 that is done only when all the items in them have been
1444 processed, not when they are opened with the exception of an
1445 empty map or array.
1446 */
1447 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1448 pDecodedItem->uDataType,
1449 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001450 if(uReturn != QCBOR_SUCCESS) {
1451 goto Done;
1452 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001453 }
1454
Laurence Lundblade02625d42020-06-25 14:41:41 -07001455 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1456 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1457 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001458 /*
1459 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001460 - A non-aggregate like an integer or string
1461 - An empty definite length map or array
1462 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001463
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001464 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001465 definite length map/array and break detection for an indefinite
1466 length map/array. If the end of the map/array was reached, then
1467 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001468 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001469 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001470 if(uReturn) {
1471 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001472 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301473 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001474
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001475 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001476 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001477 Tell the caller what level is next. This tells them what
1478 maps/arrays were closed out and makes it possible for them to
1479 reconstruct the tree with just the information returned in
1480 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001481 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001482 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001483 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001484 pDecodedItem->uNextNestLevel = 0;
1485 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001486 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001487 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001488
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001489Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001490 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001491 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001492 memset(pDecodedItem, 0, sizeof(QCBORItem));
1493 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001494 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001495}
1496
1497
Laurence Lundblade59289e52019-12-30 13:44:37 -08001498/*
1499 Mostly just assign the right data type for the date string.
1500 */
1501inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1502{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001503 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1504 return QCBOR_ERR_BAD_OPT_TAG;
1505 }
1506
1507 const UsefulBufC Temp = pDecodedItem->val.string;
1508 pDecodedItem->val.dateString = Temp;
1509 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1510 return QCBOR_SUCCESS;
1511}
1512
1513
1514/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001515 The epoch formatted date. Turns lots of different forms of encoding
1516 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001517 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001518static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001519{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001520 QCBORError nReturn = QCBOR_SUCCESS;
1521
1522 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1523
1524 switch (pDecodedItem->uDataType) {
1525
1526 case QCBOR_TYPE_INT64:
1527 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1528 break;
1529
1530 case QCBOR_TYPE_UINT64:
1531 if(pDecodedItem->val.uint64 > INT64_MAX) {
1532 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1533 goto Done;
1534 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001535 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001536 break;
1537
1538 case QCBOR_TYPE_DOUBLE:
1539 {
1540 // This comparison needs to be done as a float before
1541 // conversion to an int64_t to be able to detect doubles
1542 // that are too large to fit into an int64_t. A double
1543 // has 52 bits of preceision. An int64_t has 63. Casting
1544 // INT64_MAX to a double actually causes a round up which
1545 // is bad and wrong for the comparison because it will
1546 // allow conversion of doubles that can't fit into a
1547 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1548 // the cutoff point as if that rounds up in conversion to
1549 // double it will still be less than INT64_MAX. 0x7ff is
1550 // picked because it has 11 bits set.
1551 //
1552 // INT64_MAX seconds is on the order of 10 billion years,
1553 // and the earth is less than 5 billion years old, so for
1554 // most uses this conversion error won't occur even though
1555 // doubles can go much larger.
1556 //
1557 // Without the 0x7ff there is a ~30 minute range of time
1558 // values 10 billion years in the past and in the future
1559 // where this this code would go wrong.
1560 const double d = pDecodedItem->val.dfnum;
1561 if(d > (double)(INT64_MAX - 0x7ff)) {
1562 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1563 goto Done;
1564 }
1565 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1566 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1567 }
1568 break;
1569
1570 default:
1571 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1572 goto Done;
1573 }
1574 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1575
1576Done:
1577 return nReturn;
1578}
1579
1580
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001581/*
1582 Mostly just assign the right data type for the bignum.
1583 */
1584inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1585{
1586 // Stack Use: UsefulBuf 1 -- 16
1587 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1588 return QCBOR_ERR_BAD_OPT_TAG;
1589 }
1590 const UsefulBufC Temp = pDecodedItem->val.string;
1591 pDecodedItem->val.bigNum = Temp;
1592 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1593 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1594 : QCBOR_TYPE_NEGBIGNUM);
1595 return QCBOR_SUCCESS;
1596}
1597
1598
Laurence Lundblade59289e52019-12-30 13:44:37 -08001599#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1600/*
1601 Decode decimal fractions and big floats.
1602
1603 When called pDecodedItem must be the array that is tagged as a big
1604 float or decimal fraction, the array that has the two members, the
1605 exponent and mantissa.
1606
1607 This will fetch and decode the exponent and mantissa and put the
1608 result back into pDecodedItem.
1609 */
1610inline static QCBORError
1611QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1612{
1613 QCBORError nReturn;
1614
1615 // --- Make sure it is an array; track nesting level of members ---
1616 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1617 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1618 goto Done;
1619 }
1620
1621 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001622 // definite length arrays, but not for indefnite. Instead remember
1623 // the nesting level the two integers must be at, which is one
1624 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001625 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1626
1627 // --- Is it a decimal fraction or a bigfloat? ---
1628 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1629 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1630
1631 // --- Get the exponent ---
1632 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001633 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001634 if(nReturn != QCBOR_SUCCESS) {
1635 goto Done;
1636 }
1637 if(exponentItem.uNestingLevel != nNestLevel) {
1638 // Array is empty or a map/array encountered when expecting an int
1639 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1640 goto Done;
1641 }
1642 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1643 // Data arriving as an unsigned int < INT64_MAX has been converted
1644 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1645 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1646 // will be too large for this to handle and thus an error that will
1647 // get handled in the next else.
1648 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1649 } else {
1650 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1651 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1652 goto Done;
1653 }
1654
1655 // --- Get the mantissa ---
1656 QCBORItem mantissaItem;
1657 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1658 if(nReturn != QCBOR_SUCCESS) {
1659 goto Done;
1660 }
1661 if(mantissaItem.uNestingLevel != nNestLevel) {
1662 // Mantissa missing or map/array encountered when expecting number
1663 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1664 goto Done;
1665 }
1666 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1667 // Data arriving as an unsigned int < INT64_MAX has been converted
1668 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1669 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1670 // will be too large for this to handle and thus an error that
1671 // will get handled in an else below.
1672 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1673 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1674 // Got a good big num mantissa
1675 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1676 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001677 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1678 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1679 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001680 } else {
1681 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1682 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1683 goto Done;
1684 }
1685
1686 // --- Check that array only has the two numbers ---
1687 if(mantissaItem.uNextNestLevel == nNestLevel) {
1688 // Extra items in the decimal fraction / big num
1689 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1690 goto Done;
1691 }
1692
1693Done:
1694
1695 return nReturn;
1696}
1697#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1698
1699
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001700
1701/*
1702 */
1703inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1704{
1705 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1706 return QCBOR_ERR_BAD_OPT_TAG;
1707 }
1708 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1709 return QCBOR_SUCCESS;
1710}
1711
1712
1713inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1714{
1715 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1716 return QCBOR_ERR_BAD_OPT_TAG;
1717 }
1718 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1719 return QCBOR_SUCCESS;
1720}
1721
1722
1723inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1724{
1725 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1726 return QCBOR_ERR_BAD_OPT_TAG;
1727 }
1728 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1729 return QCBOR_SUCCESS;
1730}
1731
1732
1733inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1734{
1735 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1736 return QCBOR_ERR_BAD_OPT_TAG;
1737 }
1738 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1739 return QCBOR_SUCCESS;
1740}
1741
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001742inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1743{
1744 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1745 return QCBOR_ERR_BAD_OPT_TAG;
1746 }
1747 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1748 return QCBOR_SUCCESS;
1749}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001750
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001751
1752inline static QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
1753{
1754 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1755 return QCBOR_ERR_BAD_OPT_TAG;
1756 }
1757 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
1758 return QCBOR_SUCCESS;
1759}
1760
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001761inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1762{
1763 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1764 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
1765 } else if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1766 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1767 } else {
1768 return QCBOR_ERR_BAD_OPT_TAG;
1769 }
1770 return QCBOR_SUCCESS;
1771}
1772
1773
1774/*
1775 */
1776inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1777{
1778 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1779 return QCBOR_ERR_BAD_OPT_TAG;
1780 }
1781 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1782 return QCBOR_SUCCESS;
1783}
1784
1785
Laurence Lundblade59289e52019-12-30 13:44:37 -08001786/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001787 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001788 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001789QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001790QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001791{
1792 QCBORError nReturn;
1793
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001794 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001795 if(nReturn != QCBOR_SUCCESS) {
1796 goto Done;
1797 }
1798
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001799 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1800 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001801
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001802 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001803 nReturn = DecodeDateString(pDecodedItem);
1804 break;
1805
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001806 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001807 nReturn = DecodeDateEpoch(pDecodedItem);
1808 break;
1809
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001810 case CBOR_TAG_POS_BIGNUM:
1811 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001812 nReturn = DecodeBigNum(pDecodedItem);
1813 break;
1814
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001815 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1816 case CBOR_TAG_DECIMAL_FRACTION:
1817 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001818 // For aggregate tagged types, what goes into pTags is only collected
1819 // from the surrounding data item, not the contents, so pTags is not
1820 // passed on here.
1821
1822 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1823 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001824 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001825
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001826 case CBOR_TAG_CBOR:
1827 nReturn = DecodeWrappedCBOR(pDecodedItem);
1828 break;
1829
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001830 case CBOR_TAG_CBOR_SEQUENCE:
1831 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1832 break;
1833
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001834 case CBOR_TAG_URI:
1835 nReturn = DecodeURI(pDecodedItem);
1836 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001837
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001838 case CBOR_TAG_B64URL:
1839 nReturn = DecodeB64URL(pDecodedItem);
1840 break;
1841
1842 case CBOR_TAG_B64:
1843 nReturn = DecodeB64(pDecodedItem);
1844 break;
1845
1846 case CBOR_TAG_MIME:
1847 case CBOR_TAG_BINARY_MIME:
1848 nReturn = DecodeMIME(pDecodedItem);
1849 break;
1850
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001851 case CBOR_TAG_REGEX:
1852 nReturn = DecodeRegex(pDecodedItem);
1853 break;
1854
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001855 case CBOR_TAG_BIN_UUID:
1856 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001857 break;
1858
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001859 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001860 // The end of the tag list or no tags
1861 // Successful exit from the loop.
1862 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001863
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001864 default:
1865 // A tag that is not understood
1866 // A successful exit from the loop
1867 goto Done;
1868
1869 }
1870 if(nReturn != QCBOR_SUCCESS) {
1871 goto Done;
1872 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001873 }
1874
1875Done:
1876 if(nReturn != QCBOR_SUCCESS) {
1877 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1878 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1879 }
1880 return nReturn;
1881}
1882
1883
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001884QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1885{
1886 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1887
1888 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1889
1890 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1891
1892 return uErr;
1893}
1894
1895
Laurence Lundblade59289e52019-12-30 13:44:37 -08001896/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001897 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001898 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001899QCBORError
1900QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1901 QCBORItem *pDecodedItem,
1902 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001903{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001904 QCBORError nReturn;
1905
1906 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1907 if(nReturn != QCBOR_SUCCESS) {
1908 return nReturn;
1909 }
1910
1911 if(pTags != NULL) {
1912 pTags->uNumUsed = 0;
1913 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001914 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001915 break;
1916 }
1917 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1918 return QCBOR_ERR_TOO_MANY_TAGS;
1919 }
1920 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1921 pTags->uNumUsed++;
1922 }
1923 }
1924
1925 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001926}
1927
1928
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001929/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301930 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301931 next one down. If a layer has no work to do for a particular item
1932 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001933
Laurence Lundblade59289e52019-12-30 13:44:37 -08001934 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1935 tagged data items, turning them into the local C representation.
1936 For the most simple it is just associating a QCBOR_TYPE with the data. For
1937 the complex ones that an aggregate of data items, there is some further
1938 decoding and a little bit of recursion.
1939
1940 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301941 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301942 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001943 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001944
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301945 - GetNext_MapEntry -- This handles the combining of two
1946 items, the label and the data, that make up a map entry.
1947 It only does work on maps. It combines the label and data
1948 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001949
Laurence Lundblade59289e52019-12-30 13:44:37 -08001950 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1951 tags into bit flags associated with the data item. No actual decoding
1952 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001953
Laurence Lundblade59289e52019-12-30 13:44:37 -08001954 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301955 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301956 string allocater to create contiguous space for the item. It
1957 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001958
Laurence Lundblade59289e52019-12-30 13:44:37 -08001959 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1960 atomic data item has a "major type", an integer "argument" and optionally
1961 some content. For text and byte strings, the content is the bytes
1962 that make up the string. These are the smallest data items that are
1963 considered to be well-formed. The content may also be other data items in
1964 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001965
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001966 Roughly this takes 300 bytes of stack for vars. Need to
1967 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001968
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301969 */
1970
1971
1972/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001973 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001974 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001975int QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001976 const QCBORItem *pItem,
1977 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001978{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001979 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001980 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001981 break;
1982 }
1983 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1984 return 1;
1985 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001986 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001987
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001988 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001989}
1990
1991
1992/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001993 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001994 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001995QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001996{
Laurence Lundblade085d7952020-07-24 10:26:30 -07001997 QCBORError uReturn = me->uLastError;
1998
1999 if(uReturn != QCBOR_SUCCESS) {
2000 goto Done;
2001 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002002
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002003 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002004 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002005 uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002006 goto Done;
2007 }
2008
2009 // Error out if not all the bytes are consumed
2010 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002011 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002012 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002013
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002014Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302015 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002016 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002017 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002018
Laurence Lundblade085d7952020-07-24 10:26:30 -07002019 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002020}
2021
2022
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002023/*
2024Public function, see header qcbor/qcbor_decode.h file
2025*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002026uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2027 const QCBORItem *pItem,
2028 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002029{
2030 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
2031 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002032 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002033 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002034 }
2035}
2036
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002037
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002038/*
2039
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002040Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002041
Laurence Lundbladeee851742020-01-08 08:37:05 -08002042 - Hit end of input before it was expected while decoding type and
2043 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002044
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002045 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002046
Laurence Lundbladeee851742020-01-08 08:37:05 -08002047 - Hit end of input while decoding a text or byte string
2048 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002049
Laurence Lundbladeee851742020-01-08 08:37:05 -08002050 - Encountered conflicting tags -- e.g., an item is tagged both a date
2051 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002052
Laurence Lundbladeee851742020-01-08 08:37:05 -08002053 - Encontered an array or mapp that has too many items
2054 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002055
Laurence Lundbladeee851742020-01-08 08:37:05 -08002056 - Encountered array/map nesting that is too deep
2057 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002058
Laurence Lundbladeee851742020-01-08 08:37:05 -08002059 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2060 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002061
Laurence Lundbladeee851742020-01-08 08:37:05 -08002062 - The type of a map label is not a string or int
2063 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002064
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002065 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002066
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002067 */
2068
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002069
2070
Laurence Lundbladef6531662018-12-04 10:42:22 +09002071
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002072/* ===========================================================================
2073 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002074
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002075 This implements a simple sting allocator for indefinite length
2076 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2077 implements the function type QCBORStringAllocate and allows easy
2078 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002079
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002080 This particular allocator is built-in for convenience. The caller
2081 can implement their own. All of this following code will get
2082 dead-stripped if QCBORDecode_SetMemPool() is not called.
2083
2084 This is a very primitive memory allocator. It does not track
2085 individual allocations, only a high-water mark. A free or
2086 reallocation must be of the last chunk allocated.
2087
2088 The size of the pool and offset to free memory are packed into the
2089 first 8 bytes of the memory pool so we don't have to keep them in
2090 the decode context. Since the address of the pool may not be
2091 aligned, they have to be packed and unpacked as if they were
2092 serialized data of the wire or such.
2093
2094 The sizes packed in are uint32_t to be the same on all CPU types
2095 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002096 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002097
2098
Laurence Lundbladeee851742020-01-08 08:37:05 -08002099static inline int
2100MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002101{
2102 // Use of UsefulInputBuf is overkill, but it is convenient.
2103 UsefulInputBuf UIB;
2104
Laurence Lundbladeee851742020-01-08 08:37:05 -08002105 // Just assume the size here. It was checked during SetUp so
2106 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002107 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2108 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2109 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2110 return UsefulInputBuf_GetError(&UIB);
2111}
2112
2113
Laurence Lundbladeee851742020-01-08 08:37:05 -08002114static inline int
2115MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002116{
2117 // Use of UsefulOutBuf is overkill, but convenient. The
2118 // length check performed here is useful.
2119 UsefulOutBuf UOB;
2120
2121 UsefulOutBuf_Init(&UOB, Pool);
2122 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2123 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2124 return UsefulOutBuf_GetError(&UOB);
2125}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002126
2127
2128/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002129 Internal function for an allocation, reallocation free and destuct.
2130
2131 Having only one function rather than one each per mode saves space in
2132 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002133
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002134 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2135 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002136static UsefulBuf
2137MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002138{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002139 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002140
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002141 uint32_t uPoolSize;
2142 uint32_t uFreeOffset;
2143
2144 if(uNewSize > UINT32_MAX) {
2145 // This allocator is only good up to 4GB. This check should
2146 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2147 goto Done;
2148 }
2149 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2150
2151 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2152 goto Done;
2153 }
2154
2155 if(uNewSize) {
2156 if(pMem) {
2157 // REALLOCATION MODE
2158 // Calculate pointer to the end of the memory pool. It is
2159 // assumed that pPool + uPoolSize won't wrap around by
2160 // assuming the caller won't pass a pool buffer in that is
2161 // not in legitimate memory space.
2162 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2163
2164 // Check that the pointer for reallocation is in the range of the
2165 // pool. This also makes sure that pointer math further down
2166 // doesn't wrap under or over.
2167 if(pMem >= pPool && pMem < pPoolEnd) {
2168 // Offset to start of chunk for reallocation. This won't
2169 // wrap under because of check that pMem >= pPool. Cast
2170 // is safe because the pool is always less than UINT32_MAX
2171 // because of check in QCBORDecode_SetMemPool().
2172 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2173
2174 // Check to see if the allocation will fit. uPoolSize -
2175 // uMemOffset will not wrap under because of check that
2176 // pMem is in the range of the uPoolSize by check above.
2177 if(uNewSize <= uPoolSize - uMemOffset) {
2178 ReturnValue.ptr = pMem;
2179 ReturnValue.len = uNewSize;
2180
2181 // Addition won't wrap around over because uNewSize was
2182 // checked to be sure it is less than the pool size.
2183 uFreeOffset = uMemOffset + uNewSize32;
2184 }
2185 }
2186 } else {
2187 // ALLOCATION MODE
2188 // uPoolSize - uFreeOffset will not underflow because this
2189 // pool implementation makes sure uFreeOffset is always
2190 // smaller than uPoolSize through this check here and
2191 // reallocation case.
2192 if(uNewSize <= uPoolSize - uFreeOffset) {
2193 ReturnValue.len = uNewSize;
2194 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002195 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002196 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002197 }
2198 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002199 if(pMem) {
2200 // FREE MODE
2201 // Cast is safe because of limit on pool size in
2202 // QCBORDecode_SetMemPool()
2203 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2204 } else {
2205 // DESTRUCT MODE
2206 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002207 }
2208 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002209
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002210 UsefulBuf Pool = {pPool, uPoolSize};
2211 MemPool_Pack(Pool, uFreeOffset);
2212
2213Done:
2214 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002215}
2216
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002217
Laurence Lundbladef6531662018-12-04 10:42:22 +09002218/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002219 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002220 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002221QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2222 UsefulBuf Pool,
2223 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002224{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002225 // The pool size and free mem offset are packed into the beginning
2226 // of the pool memory. This compile time check make sure the
2227 // constant in the header is correct. This check should optimize
2228 // down to nothing.
2229 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002230 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002231 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002232
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002233 // The pool size and free offset packed in to the beginning of pool
2234 // memory are only 32-bits. This check will optimize out on 32-bit
2235 // machines.
2236 if(Pool.len > UINT32_MAX) {
2237 return QCBOR_ERR_BUFFER_TOO_LARGE;
2238 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002239
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002240 // This checks that the pool buffer given is big enough.
2241 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2242 return QCBOR_ERR_BUFFER_TOO_SMALL;
2243 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002244
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002245 pMe->StringAllocator.pfAllocator = MemPool_Function;
2246 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2247 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002248
Laurence Lundblade30816f22018-11-10 13:40:22 +07002249 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002250}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002251
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002252
2253
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002254
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002255
2256
2257/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002258 Consume an entire map or array (and do next to
2259 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002260 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002261static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002262ConsumeItem(QCBORDecodeContext *pMe,
2263 const QCBORItem *pItemToConsume,
2264 uint_fast8_t *puNextNestLevel)
2265{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002266 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002267 QCBORItem Item;
2268
Laurence Lundblade02625d42020-06-25 14:41:41 -07002269 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002270
Laurence Lundblade02625d42020-06-25 14:41:41 -07002271 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002272 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002273
Laurence Lundblade1341c592020-04-11 14:19:05 -07002274 /* This works for definite and indefinite length
2275 * maps and arrays by using the nesting level
2276 */
2277 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002278 uReturn = QCBORDecode_GetNext(pMe, &Item);
2279 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002280 goto Done;
2281 }
2282 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002283
Laurence Lundblade1341c592020-04-11 14:19:05 -07002284 if(puNextNestLevel != NULL) {
2285 *puNextNestLevel = Item.uNextNestLevel;
2286 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002287 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002288
Laurence Lundblade1341c592020-04-11 14:19:05 -07002289 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002290 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002291 if(puNextNestLevel != NULL) {
2292 /* Just pass the nesting level through */
2293 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2294 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002295 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002296 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002297
2298Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002299 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002300}
2301
2302
Laurence Lundblade1341c592020-04-11 14:19:05 -07002303/* Return true if the labels in Item1 and Item2 are the same.
2304 Works only for integer and string labels. Returns false
2305 for any other type. */
2306static inline bool
2307MatchLabel(QCBORItem Item1, QCBORItem Item2)
2308{
2309 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2310 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2311 return true;
2312 }
2313 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002314 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002315 return true;
2316 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002317 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002318 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2319 return true;
2320 }
2321 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2322 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2323 return true;
2324 }
2325 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002326
Laurence Lundblade1341c592020-04-11 14:19:05 -07002327 /* Other label types are never matched */
2328 return false;
2329}
2330
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002331
2332/*
2333 Returns true if Item1 and Item2 are the same type
2334 or if either are of QCBOR_TYPE_ANY.
2335 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002336static inline bool
2337MatchType(QCBORItem Item1, QCBORItem Item2)
2338{
2339 if(Item1.uDataType == Item2.uDataType) {
2340 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002341 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002342 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002343 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002344 return true;
2345 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002346 return false;
2347}
2348
2349
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002350/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002351 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002352
2353 @param[in] pMe The decode context to search.
2354 @param[in,out] pItemArray The items to search for and the items found.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002355 @param[out] puOffset Byte offset of last item matched.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002356 @param[in] pCBContext Context for the not-found item call back
2357 @param[in] pfCallback Function to call on items not matched in pItemArray
2358
2359 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2360
2361 @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.
2362
2363 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2364
2365 @retval Also errors returned by QCBORDecode_GetNext().
2366
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002367 On input pItemArray contains a list of labels and data types
2368 of items to be found.
2369
2370 On output the fully retrieved items are filled in with
2371 values and such. The label was matched, so it never changes.
2372
2373 If an item was not found, its data type is set to none.
2374
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002375 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002376static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002377MapSearch(QCBORDecodeContext *pMe,
2378 QCBORItem *pItemArray,
2379 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002380 void *pCBContext,
2381 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002382{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002383 QCBORError uReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002384
Laurence Lundblade085d7952020-07-24 10:26:30 -07002385 QCBORDecodeNesting SaveNesting = pMe->nesting; // TODO: refactor?
2386
2387 uint64_t uFoundItemBitMap = 0;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002388
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002389 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
2390 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2391 /* QCBOR_TYPE_NONE as first item indicates just looking
2392 for the end of an array, so don't give error. */
2393 uReturn = QCBOR_ERR_NOT_A_MAP;
2394 goto Done;
2395 }
2396
Laurence Lundblade085d7952020-07-24 10:26:30 -07002397 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2398 // It is an empty bounded array or map
2399 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2400 // Just trying to find the end of the map or array
2401 uReturn = QCBOR_SUCCESS;
2402 pMe->uMapEndOffsetCache = (uint32_t)DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
2403 } else {
2404 // Nothing is ever found in an empty array or map
2405 uReturn = QCBOR_SUCCESS;
2406 }
2407 goto Done;
2408 }
2409
2410 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2411
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002412 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002413 UsefulInputBuf_Seek(&(pMe->InBuf),
2414 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002415
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002416 /*
2417 Loop over all the items in the map. They could be
2418 deeply nested and this should handle both definite
2419 and indefinite length maps and arrays, so this
2420 adds some complexity.
2421 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002422 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002423
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002424 uint_fast8_t uNextNestLevel;
2425
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002426
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002427 /* Iterate over items in the map / array */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002428 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002429 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002430 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002431
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002432 /* Get the item */
2433 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002434 uReturn = QCBORDecode_GetNext(pMe, &Item);
2435 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002436 /* Got non-well-formed CBOR */
2437 goto Done;
2438 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002439
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002440 /* See if item has one of the labels that are of interest */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002441 int nIndex;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002442 QCBORItem *pIterator;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002443 for(pIterator = pItemArray, nIndex = 0; pIterator->uLabelType != 0; pIterator++, nIndex++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002444 if(MatchLabel(Item, *pIterator)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002445 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002446 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2447 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002448 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002449 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002450 /* Also try to match its type */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002451 if(!MatchType(Item, *pIterator)) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002452 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002453 goto Done;
2454 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002455
2456 /* Successful match. Return the item. */
2457 *pIterator = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002458 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002459 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002460 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002461 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002462 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002463 /*
2464 Call the callback on unmatched labels.
2465 (It is tempting to do duplicate detection here, but that would
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002466 require dynamic memory allocation because the number of labels
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002467 that might be encountered is unbounded.)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002468 */
2469 if(pfCallback) {
2470 uReturn = (*pfCallback)(pCBContext, &Item);
2471 if(uReturn != QCBOR_SUCCESS) {
2472 goto Done;
2473 }
2474 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002475 }
2476 }
2477
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002478 /*
2479 Consume the item whether matched or not. This
2480 does the work of traversing maps and array and
2481 everything in them. In this loop only the
2482 items at the current nesting level are examined
2483 to match the labels.
2484 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002485 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2486 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002487 goto Done;
2488 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002489
2490 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002491
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002492 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002493
2494 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002495 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2496 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002497
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002498 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade085d7952020-07-24 10:26:30 -07002499Done:
2500 {int i;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002501 QCBORItem *pIterator;
2502 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002503 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002504 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002505 }
2506 }
Laurence Lundblade085d7952020-07-24 10:26:30 -07002507 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002508
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002509 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002510
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002511 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002512}
2513
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002514
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002515/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002516 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002517*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002518void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2519 int64_t nLabel,
2520 uint8_t uQcborType,
2521 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002522{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002523 if(pMe->uLastError != QCBOR_SUCCESS) {
2524 return;
2525 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002526
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002527 QCBORItem OneItemSeach[2];
2528 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2529 OneItemSeach[0].label.int64 = nLabel;
2530 OneItemSeach[0].uDataType = uQcborType;
2531 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002532
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002533 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2534 if(uReturn != QCBOR_SUCCESS) {
2535 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002536 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002537 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002538 uReturn = QCBOR_ERR_NOT_FOUND;
2539 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002540 }
2541
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002542 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002543
2544 Done:
2545 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002546}
2547
2548
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002549/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002550 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002551*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002552void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2553 const char *szLabel,
2554 uint8_t uQcborType,
2555 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002556{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002557 if(pMe->uLastError != QCBOR_SUCCESS) {
2558 return;
2559 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002560
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002561 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002562 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2563 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2564 OneItemSeach[0].uDataType = uQcborType;
2565 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002566
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002567 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2568 if(uReturn != QCBOR_SUCCESS) {
2569 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002570 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002571 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002572 uReturn = QCBOR_ERR_NOT_FOUND;
2573 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002574 }
2575
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002576 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002577
2578Done:
2579 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002580}
2581
2582
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002583
2584static QCBORError CheckTypeList(uint8_t uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
2585{
2586 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2587 if(uDataType == puTypeList[i]) {
2588 return QCBOR_SUCCESS;
2589 }
2590 }
2591 return QCBOR_ERR_UNEXPECTED_TYPE;
2592}
2593
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002594/**
2595 @param[in] TagSpec Specification for matching tags.
2596 @param[in] uDataType A QCBOR data type
2597
2598 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2599 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2600
2601 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2602 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002603static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002604{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002605 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002606 // Must match the tag and only the tag
2607 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002608 }
2609
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002610 QCBORError uReturn = CheckTypeList(uDataType, TagSpec.uAllowedContentTypes);
2611 if(uReturn == QCBOR_SUCCESS) {
2612 return QCBOR_SUCCESS;
2613 }
2614
2615 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
2616 /* Must match the content type and only the content type.
2617 There was no match just above so it is a fail. */
2618 return QCBOR_ERR_UNEXPECTED_TYPE;
2619 }
2620
2621 /* If here it can match either the tag or the content
2622 and it hasn't matched the content, so the end
2623 result is whether it matches the tag. This is
2624 also the case that the CBOR standard discourages. */
2625
2626 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002627}
2628
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002629
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002630// Semi-private
2631// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002632void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2633 int64_t nLabel,
2634 TagSpecification TagSpec,
2635 QCBORItem *pItem)
2636{
2637 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2638 if(pMe->uLastError != QCBOR_SUCCESS) {
2639 return;
2640 }
2641
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002642 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002643}
2644
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002645// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002646void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2647 const char *szLabel,
2648 TagSpecification TagSpec,
2649 QCBORItem *pItem)
2650{
2651 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2652 if(pMe->uLastError != QCBOR_SUCCESS) {
2653 return;
2654 }
2655
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002656 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002657}
2658
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002659// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002660void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2661 int64_t nLabel,
2662 TagSpecification TagSpec,
2663 UsefulBufC *pString)
2664{
2665 QCBORItem Item;
2666 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2667 if(pMe->uLastError == QCBOR_SUCCESS) {
2668 *pString = Item.val.string;
2669 }
2670}
2671
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002672// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002673void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2674 const char * szLabel,
2675 TagSpecification TagSpec,
2676 UsefulBufC *pString)
2677{
2678 QCBORItem Item;
2679 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2680 if(pMe->uLastError == QCBOR_SUCCESS) {
2681 *pString = Item.val.string;
2682 }
2683}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002684
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002685/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002686 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002687*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002688QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2689{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002690 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002691}
2692
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002693/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002694 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002695*/
2696QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2697 QCBORItem *pItemList,
2698 void *pCallbackCtx,
2699 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002700{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002701 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002702}
2703
2704
Laurence Lundblade34691b92020-05-18 22:25:25 -07002705static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002706{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002707 // TODO: check that only one item is in pSearch?
Laurence Lundblade34691b92020-05-18 22:25:25 -07002708 if(pMe->uLastError != QCBOR_SUCCESS) {
2709 // Already in error state; do nothing.
2710 return;
2711 }
2712
2713 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002714 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002715 if(pMe->uLastError != QCBOR_SUCCESS) {
2716 return;
2717 }
2718
Laurence Lundblade085d7952020-07-24 10:26:30 -07002719 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
2720 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
2721 return;
2722 }
2723
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002724 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002725 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002726
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002727 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002728 be at the right place.
2729
2730 The UsefulInBuf offset could be anywhere, so no assumption is
2731 made about it.
2732
2733 No assumption is made about the pre-order nesting level either.
2734
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002735 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002736 the map level that is being entered.
2737 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002738 /* Seek to the data item that is the map or array */
2739 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002740
2741 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002742
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002743 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002744}
2745
2746
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002747/*
2748Public function, see header qcbor/qcbor_decode.h file
2749*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002750void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002751{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002752 QCBORItem OneItemSeach[2];
2753 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2754 OneItemSeach[0].label.int64 = nLabel;
2755 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2756 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002757
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002758 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002759 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002760}
2761
2762
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002763/*
2764Public function, see header qcbor/qcbor_decode.h file
2765*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002766void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002767{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002768 QCBORItem OneItemSeach[2];
2769 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2770 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2771 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2772 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002773
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002774 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002775}
2776
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002777/*
2778Public function, see header qcbor/qcbor_decode.h file
2779*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002780void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002781{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002782 QCBORItem OneItemSeach[2];
2783 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2784 OneItemSeach[0].label.int64 = nLabel;
2785 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2786 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002787
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002788 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002789}
2790
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002791/*
2792Public function, see header qcbor/qcbor_decode.h file
2793*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002794void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2795{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002796 QCBORItem OneItemSeach[2];
2797 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2798 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2799 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2800 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002801
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002802 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002803}
2804
2805
Laurence Lundblade02625d42020-06-25 14:41:41 -07002806// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002807void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002808{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002809 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002810 if(pMe->uLastError != QCBOR_SUCCESS) {
2811 // Already in error state; do nothing.
2812 return;
2813 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002814
2815 /* Get the data item that is the map that is being searched */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002816 QCBORItem Item;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002817 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002818 if(pMe->uLastError != QCBOR_SUCCESS) {
2819 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002820 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002821 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002822 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2823 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002824 }
2825
Laurence Lundblade085d7952020-07-24 10:26:30 -07002826 const bool bIsEmpty = Item.uNestingLevel == Item.uNextNestLevel;
2827 if(bIsEmpty) {
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002828 // Special case to increment nesting level for zero-length maps and arrays entered in bounded mode.
2829 DecodeNesting_Descend(&(pMe->nesting), uType);
2830 }
2831
Laurence Lundblade02625d42020-06-25 14:41:41 -07002832 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002833
Laurence Lundblade085d7952020-07-24 10:26:30 -07002834 QCBORError uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002835 UsefulInputBuf_Tell(&(pMe->InBuf)));
2836
2837 pMe->uLastError = (uint8_t)uErr;
2838
Laurence Lundblade02625d42020-06-25 14:41:41 -07002839 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002840}
2841
Laurence Lundblade02625d42020-06-25 14:41:41 -07002842
2843/*
2844 This is for exiting a level that is a bounded map, array or bstr
2845 wrapped CBOR. It is the work common to these.
2846
2847 One chunk of work is to set up the pre-order traversal so it is at
2848 the item just after the bounded map, array or bstr that is being
2849 exited. This is somewhat complex.
2850
2851 The other work is to level-up the bounded mode to next higest bounded
2852 mode or the top level if there isn't one.
2853 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002854static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002855ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002856{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002857 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002858
Laurence Lundblade02625d42020-06-25 14:41:41 -07002859 /*
2860 First the pre-order-traversal byte offset is positioned to the
2861 item just after the bounded mode item that was just consumed.
2862 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002863 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2864
Laurence Lundblade02625d42020-06-25 14:41:41 -07002865 /*
2866 Next, set the current nesting level to one above the bounded level
2867 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002868
Laurence Lundblade02625d42020-06-25 14:41:41 -07002869 DecodeNesting_CheckBoundedType() is always called before this and
2870 makes sure pCurrentBounded is valid.
2871 */
2872 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2873
2874 /*
2875 This does the complex work of leveling up the pre-order traversal
2876 when the end of a map or array or another bounded level is
2877 reached. It may do nothing, or ascend all the way to the top
2878 level.
2879 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07002880 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002881 if(uErr != QCBOR_SUCCESS) {
2882 goto Done;
2883 }
2884
Laurence Lundblade02625d42020-06-25 14:41:41 -07002885 /*
2886 This makes the next highest bounded level the current bounded
2887 level. If there is no next highest level, then no bounded mode is
2888 in effect.
2889 */
2890 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002891
Laurence Lundblade02625d42020-06-25 14:41:41 -07002892 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002893
2894Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002895 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002896 return uErr;
2897}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002898
Laurence Lundblade02625d42020-06-25 14:41:41 -07002899
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002900// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002901void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002902{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002903 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002904 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002905 return;
2906 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002907
Laurence Lundblade02625d42020-06-25 14:41:41 -07002908 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002909
Laurence Lundblade02625d42020-06-25 14:41:41 -07002910 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002911 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2912 goto Done;
2913 }
2914
Laurence Lundblade02625d42020-06-25 14:41:41 -07002915 /*
2916 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002917 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002918 from previous map search, then do a dummy search.
2919 */
2920 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002921 QCBORItem Dummy;
2922 Dummy.uLabelType = QCBOR_TYPE_NONE;
2923 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2924 if(uErr != QCBOR_SUCCESS) {
2925 goto Done;
2926 }
2927 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002928
Laurence Lundblade02625d42020-06-25 14:41:41 -07002929 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002930
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002931Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002932 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002933}
2934
2935
Laurence Lundblade1341c592020-04-11 14:19:05 -07002936void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002937{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002938 // TODO: check for map mode; test this
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002939 //pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->u.ma.uCountTotal;
2940 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->u.ma.uStartOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002941}
2942
2943
Laurence Lundblade1341c592020-04-11 14:19:05 -07002944
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002945static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002946 const QCBORItem *pItem,
2947 uint8_t uTagRequirement,
2948 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002949{
2950 if(pMe->uLastError != QCBOR_SUCCESS) {
2951 // Already in error state; do nothing.
2952 return pMe->uLastError;
2953 }
2954
2955 QCBORError uError = QCBOR_SUCCESS;
2956
2957 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2958 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2959 goto Done;;
2960 }
2961
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002962 const TagSpecification TagSpec = {uTagRequirement,
2963 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
2964 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
2965 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002966
2967 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2968 if(uError != QCBOR_SUCCESS) {
2969 goto Done;
2970 }
2971
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002972 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002973 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002974 so the increment in NestLevelAscender called by ExitBoundedLevel()
2975 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002976 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002977 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002978
2979 if(pBstr) {
2980 *pBstr = pItem->val.string;
2981 }
2982
2983 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002984
2985 // Need to move UIB input cursor to the right place
2986
2987 // Really this is a subtraction and an assignment; not much code
2988 // There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002989 // The bstr was just consumed so the cursor is at the next item after it
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002990
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002991 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002992
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002993 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
2994
2995 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002996
Laurence Lundblade02625d42020-06-25 14:41:41 -07002997 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
2998 uPreviousLength,
2999 uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003000Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07003001 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003002
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003003 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003004}
3005
3006
Laurence Lundblade02625d42020-06-25 14:41:41 -07003007/*
3008 Public function, see header qcbor/qcbor_decode.h file
3009 */
3010void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003011 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003012 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003013{
3014 if(pMe->uLastError != QCBOR_SUCCESS) {
3015 // Already in error state; do nothing.
3016 return;
3017 }
3018
3019 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003020 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003021 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3022 if(pMe->uLastError != QCBOR_SUCCESS) {
3023 return;
3024 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003025
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003026 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003027 &Item,
3028 uTagRequirement,
3029 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003030}
3031
3032
Laurence Lundblade02625d42020-06-25 14:41:41 -07003033/*
3034 Public function, see header qcbor/qcbor_decode.h file
3035 */
3036void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
3037 uint8_t uTagRequirement,
3038 int64_t nLabel,
3039 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003040{
3041 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003042 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003043
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003044 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003045}
3046
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003047
Laurence Lundblade02625d42020-06-25 14:41:41 -07003048/*
3049 Public function, see header qcbor/qcbor_decode.h file
3050 */
3051void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
3052 uint8_t uTagRequirement,
3053 const char *szLabel,
3054 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003055{
3056 QCBORItem Item;
3057 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3058
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003059 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003060}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003061
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003062
Laurence Lundblade02625d42020-06-25 14:41:41 -07003063/*
3064 Public function, see header qcbor/qcbor_decode.h file
3065 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003066void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003067{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003068 if(pMe->uLastError != QCBOR_SUCCESS) {
3069 // Already in error state; do nothing.
3070 return;
3071 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003072
Laurence Lundblade02625d42020-06-25 14:41:41 -07003073 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3074 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3075 return;
3076 }
3077
3078 /*
3079 Reset the length of the UsefulInputBuf to what it was before
3080 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003081 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003082 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3083 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003084
3085
Laurence Lundblade02625d42020-06-25 14:41:41 -07003086 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003087 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003088}
3089
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003090
Laurence Lundbladee6430642020-03-14 21:15:44 -07003091
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003092
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003093
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003094
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003095
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003096
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003097static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3098{
3099 switch(pItem->uDataType) {
3100 case QCBOR_TYPE_TRUE:
3101 *pBool = true;
3102 return QCBOR_SUCCESS;
3103 break;
3104
3105 case QCBOR_TYPE_FALSE:
3106 *pBool = false;
3107 return QCBOR_SUCCESS;
3108 break;
3109
3110 default:
3111 return QCBOR_ERR_UNEXPECTED_TYPE;
3112 break;
3113 }
3114}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003115
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003116/*
3117Public function, see header qcbor/qcbor_decode.h file
3118*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003119void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003120{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003121 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003122 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003123 return;
3124 }
3125
Laurence Lundbladec4537442020-04-14 18:53:22 -07003126 QCBORError nError;
3127 QCBORItem Item;
3128
3129 nError = QCBORDecode_GetNext(pMe, &Item);
3130 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003131 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003132 return;
3133 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003134 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003135}
3136
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003137/*
3138Public function, see header qcbor/qcbor_decode.h file
3139*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003140void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003141{
3142 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003143 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003144
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003145 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003146}
3147
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003148/*
3149Public function, see header qcbor/qcbor_decode.h file
3150*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003151void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3152{
3153 QCBORItem Item;
3154 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3155
3156 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3157}
3158
3159
3160
3161void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003162{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003163 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003164 // Already in error state, do nothing
3165 return;
3166 }
3167
3168 QCBORError nError;
3169 QCBORItem Item;
3170
3171 nError = QCBORDecode_GetNext(pMe, &Item);
3172 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003173 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003174 return;
3175 }
3176
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003177 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3178
3179 if(pMe->uLastError == QCBOR_SUCCESS) {
3180 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003181 }
3182}
3183
Laurence Lundbladec4537442020-04-14 18:53:22 -07003184
3185
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003186
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003187static QCBORError ConvertBigNum(uint8_t uTagRequirement,
3188 const QCBORItem *pItem,
3189 UsefulBufC *pValue,
3190 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003191{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003192 const TagSpecification TagSpec = {uTagRequirement,
3193 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3194 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3195 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003196
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003197 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
3198 if(uErr != QCBOR_SUCCESS) {
3199 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003200 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003201
3202 *pValue = pItem->val.string;
3203
3204 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3205 *pbIsNegative = false;
3206 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3207 *pbIsNegative = true;
3208 }
3209
3210 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003211}
3212
3213
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003214/**
3215 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003216 */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003217void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003218{
3219 if(pMe->uLastError != QCBOR_SUCCESS) {
3220 // Already in error state, do nothing
3221 return;
3222 }
3223
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003224 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003225 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3226 if(uError != QCBOR_SUCCESS) {
3227 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003228 return;
3229 }
3230
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003231 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003232}
3233
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003234/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003235Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003236*/
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003237void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003238{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003239 QCBORItem Item;
3240 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003241
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003242 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003243}
3244
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003245/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003246Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003247*/
3248void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
3249{
3250 QCBORItem Item;
3251 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3252
3253 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
3254}
3255
3256
3257
3258// Semi private
3259QCBORError FarfMIME(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsNot7Bit)
3260{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003261
3262
3263 const TagSpecification TagSpecText = {uTagRequirement,
3264 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3265 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3266 };
3267 const TagSpecification TagSpecBinary = {uTagRequirement,
3268 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3269 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3270 };
3271
3272
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003273 QCBORError uReturn;
3274
3275 if(CheckTagRequirement(TagSpecText, pItem->uDataType)) {
3276 *pMessage = pItem->val.string;
3277 if(pbIsNot7Bit != NULL) {
3278 *pbIsNot7Bit = false;
3279 }
3280 uReturn = QCBOR_SUCCESS;
3281 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType)) {
3282 *pMessage = pItem->val.string;
3283 if(pbIsNot7Bit != NULL) {
3284 *pbIsNot7Bit = true;
3285 }
3286 uReturn = QCBOR_SUCCESS;
3287
3288 } else {
3289 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3290 }
3291
3292 return uReturn;
3293}
3294
3295
3296
3297
3298
Laurence Lundbladec4537442020-04-14 18:53:22 -07003299
3300
3301
Laurence Lundbladee6430642020-03-14 21:15:44 -07003302
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003303typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003304
3305
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003306// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003307static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003308{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003309 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003310
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003311 if(uResult != 0) {
3312 /* This loop will run a maximum of 19 times because
3313 * UINT64_MAX < 10 ^^ 19. More than that will cause
3314 * exit with the overflow error
3315 */
3316 for(; nExponent > 0; nExponent--) {
3317 if(uResult > UINT64_MAX / 10) {
3318 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3319 }
3320 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003321 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003322
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003323 for(; nExponent < 0; nExponent++) {
3324 uResult = uResult / 10;
3325 if(uResult == 0) {
3326 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3327 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003328 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003329 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003330 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003331
3332 *puResult = uResult;
3333
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003334 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003335}
3336
3337
Laurence Lundbladee6430642020-03-14 21:15:44 -07003338/* Convert a decimal fraction to an int64_t without using
3339 floating point or math libraries. Most decimal fractions
3340 will not fit in an int64_t and this will error out with
3341 under or overflow
3342 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003343static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003344{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003345 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003346
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003347 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003348
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003349 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003350 * INT64_MAX < 2^31. More than that will cause
3351 * exist with the overflow error
3352 */
3353 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003354 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003355 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003356 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003357 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003358 nExponent--;
3359 }
3360
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003361 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003362 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003363 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3364 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003365 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003366 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003367 }
3368
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003369 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003370
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003371 return QCBOR_SUCCESS;
3372}
3373
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003374/*
3375 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3376 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003377static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3378{
3379 uint64_t uResult;
3380
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003381 // Take the absolute value of the mantissa and convert to unsigned.
3382 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003383 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3384
3385 // Do the exponentiation of the positive mantissa
3386 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3387 if(uReturn) {
3388 return uReturn;
3389 }
3390
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003391
Laurence Lundblade983500d2020-05-14 11:49:34 -07003392 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3393 of INT64_MIN. This assumes two's compliment representation where
3394 INT64_MIN is one increment farther from 0 than INT64_MAX.
3395 Trying to write -INT64_MIN doesn't work to get this because the
3396 compiler tries to work with an int64_t which can't represent
3397 -INT64_MIN.
3398 */
3399 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3400
3401 // Error out if too large
3402 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003403 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3404 }
3405
3406 // Casts are safe because of checks above
3407 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3408
3409 return QCBOR_SUCCESS;
3410}
3411
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003412/*
3413 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3414 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003415static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3416{
3417 if(nMantissa < 0) {
3418 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3419 }
3420
3421 // Cast to unsigned is OK because of check for negative
3422 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3423 // Exponentiation is straight forward
3424 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3425}
3426
3427
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003428#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003429
3430
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003431static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003432{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003433 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003434
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003435 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003436 const uint8_t *pByte = BigNum.ptr;
3437 size_t uLen = BigNum.len;
3438 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003439 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003440 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003441 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003442 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003443 }
3444
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003445 *pResult = uResult;
3446 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003447}
3448
Laurence Lundblade887add82020-05-17 05:50:34 -07003449static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003450{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003451 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003452}
3453
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003454static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003455{
3456 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003457 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3458 if(uError) {
3459 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003460 }
3461 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3462 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003463 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003464}
3465
3466
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003467static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003468{
3469 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003470 /* negaative int furthest from zero is INT64_MIN
3471 which is expressed as -INT64_MAX-1. The value of
3472 a negative bignum is -n-1, one further from zero
3473 than the positive bignum */
3474
3475 /* say INT64_MIN is -2; then INT64_MAX is 1.
3476 Then -n-1 <= INT64_MIN.
3477 Then -n -1 <= -INT64_MAX - 1
3478 THen n <= INT64_MAX. */
3479 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003480 if(uError) {
3481 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003482 }
3483 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003484 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003485 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003486 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003487 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003488}
3489
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003490#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003491
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003492
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003493/*
3494Convert a integers and floats to an int64_t.
3495
3496\param[in] uOptions Bit mask list of conversion options.
3497
3498\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3499
3500\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3501
3502\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3503
3504*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003505static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3506{
3507 switch(pItem->uDataType) {
3508 // TODO: float when ifdefs are set
3509 case QCBOR_TYPE_DOUBLE:
3510 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3511 // TODO: what about under/overflow here?
3512 // Invokes the floating-point HW and/or compiler-added libraries
3513 feclearexcept(FE_ALL_EXCEPT);
3514 *pnValue = llround(pItem->val.dfnum);
3515 if(fetestexcept(FE_INVALID)) {
3516 // TODO: better error code
3517 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3518 }
3519 } else {
3520 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3521 }
3522 break;
3523
3524 case QCBOR_TYPE_INT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003525 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003526 *pnValue = pItem->val.int64;
3527 } else {
3528 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3529 }
3530 break;
3531
3532 case QCBOR_TYPE_UINT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003533 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003534 if(pItem->val.uint64 < INT64_MAX) {
3535 *pnValue = pItem->val.int64;
3536 } else {
3537 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3538 }
3539 } else {
3540 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3541 }
3542 break;
3543
3544 default:
3545 return QCBOR_ERR_UNEXPECTED_TYPE;
3546 }
3547 return QCBOR_SUCCESS;
3548}
3549
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003550
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003551void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
3552 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003553 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003554 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003555{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003556 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003557 return;
3558 }
3559
Laurence Lundbladee6430642020-03-14 21:15:44 -07003560 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003561 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3562 if(uError) {
3563 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003564 return;
3565 }
3566
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003567 if(pItem) {
3568 *pItem = Item;
3569 }
3570
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003571 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003572}
3573
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003574
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003575void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3576 int64_t nLabel,
3577 uint32_t uOptions,
3578 int64_t *pnValue,
3579 QCBORItem *pItem)
3580{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003581 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003582 if(pMe->uLastError != QCBOR_SUCCESS) {
3583 return;
3584 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003585
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003586 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003587}
3588
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003589
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003590void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3591 const char * szLabel,
3592 uint32_t uOptions,
3593 int64_t *pnValue,
3594 QCBORItem *pItem)
3595{
3596 if(pMe->uLastError != QCBOR_SUCCESS) {
3597 return;
3598 }
3599
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003600 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003601 if(pMe->uLastError != QCBOR_SUCCESS) {
3602 return;
3603 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003604
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003605 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003606}
3607
3608
3609
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003610/*
3611 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003612
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003613 \param[in] uOptions Bit mask list of conversion options.
3614
3615 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3616
3617 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3618
3619 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3620
3621 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003622static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3623{
3624 QCBORError uErr;
3625
3626 switch(pItem->uDataType) {
3627
3628 case QCBOR_TYPE_POSBIGNUM:
3629 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3630 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003631 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003632 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003633 }
3634 break;
3635
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003636 case QCBOR_TYPE_NEGBIGNUM:
3637 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3638 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003639 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003640 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003641 }
3642 break;
3643
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003644#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3645 case QCBOR_TYPE_DECIMAL_FRACTION:
3646 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3647 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3648 pItem->val.expAndMantissa.nExponent,
3649 pnValue,
3650 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003651 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003652 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3653 }
3654 break;
3655
3656 case QCBOR_TYPE_BIGFLOAT:
3657 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3658 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3659 pItem->val.expAndMantissa.nExponent,
3660 pnValue,
3661 Exponentitate2);
3662 } else {
3663 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3664 }
3665 break;
3666
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003667 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3668 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3669 int64_t nMantissa;
3670 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3671 if(uErr) {
3672 return uErr;
3673 }
3674 return ExponentiateNN(nMantissa,
3675 pItem->val.expAndMantissa.nExponent,
3676 pnValue,
3677 Exponentitate10);
3678 } else {
3679 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3680 }
3681 break;
3682
3683 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3684 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3685 int64_t nMantissa;
3686 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3687 if(uErr) {
3688 return uErr;
3689 }
3690 return ExponentiateNN(nMantissa,
3691 pItem->val.expAndMantissa.nExponent,
3692 pnValue,
3693 Exponentitate10);
3694 } else {
3695 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3696 }
3697 break;
3698
3699 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3700 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3701 int64_t nMantissa;
3702 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3703 if(uErr) {
3704 return uErr;
3705 }
3706 return ExponentiateNN(nMantissa,
3707 pItem->val.expAndMantissa.nExponent,
3708 pnValue,
3709 Exponentitate2);
3710 } else {
3711 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3712 }
3713 break;
3714
3715 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3716 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3717 int64_t nMantissa;
3718 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3719 if(uErr) {
3720 return uErr;
3721 }
3722 return ExponentiateNN(nMantissa,
3723 pItem->val.expAndMantissa.nExponent,
3724 pnValue,
3725 Exponentitate2);
3726 } else {
3727 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003728 }
3729 break;
3730
Laurence Lundbladec4537442020-04-14 18:53:22 -07003731 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003732 return QCBOR_ERR_UNEXPECTED_TYPE;
3733#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07003734 }
3735}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003736
3737
Laurence Lundbladec4537442020-04-14 18:53:22 -07003738/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003739 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003740 */
3741void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003742{
3743 QCBORItem Item;
3744
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003745 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003746
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003747 if(pMe->uLastError == QCBOR_SUCCESS) {
3748 // The above conversion succeeded
3749 return;
3750 }
3751
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003752 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003753 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003754 return;
3755 }
3756
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003757 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003758}
3759
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003760
3761/*
3762Public function, see header qcbor/qcbor_decode.h file
3763*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003764void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
3765{
3766 QCBORItem Item;
3767
3768 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
3769
3770 if(pMe->uLastError == QCBOR_SUCCESS) {
3771 // The above conversion succeeded
3772 return;
3773 }
3774
3775 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3776 // The above conversion failed in a way that code below can't correct
3777 return;
3778 }
3779
3780 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3781}
3782
3783
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003784/*
3785Public function, see header qcbor/qcbor_decode.h file
3786*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003787void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3788{
3789 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003790 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3791
3792 if(pMe->uLastError == QCBOR_SUCCESS) {
3793 // The above conversion succeeded
3794 return;
3795 }
3796
3797 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3798 // The above conversion failed in a way that code below can't correct
3799 return;
3800 }
3801
3802 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3803}
3804
3805
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003806static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3807{
3808 switch(pItem->uDataType) {
3809 // TODO: type flaot
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07003810 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003811 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3812 feclearexcept(FE_ALL_EXCEPT);
3813 double dRounded = round(pItem->val.dfnum);
3814 // TODO: over/underflow
3815 if(fetestexcept(FE_INVALID)) {
3816 // TODO: better error code
3817 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3818 } else if(isnan(dRounded)) {
3819 // TODO: better error code
3820 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3821 } else if(dRounded >= 0) {
3822 *puValue = (uint64_t)dRounded;
3823 } else {
3824 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3825 }
3826 } else {
3827 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3828 }
3829 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003830
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003831 case QCBOR_TYPE_INT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003832 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003833 if(pItem->val.int64 >= 0) {
3834 *puValue = (uint64_t)pItem->val.int64;
3835 } else {
3836 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3837 }
3838 } else {
3839 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3840 }
3841 break;
3842
3843 case QCBOR_TYPE_UINT64:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003844 if(uOptions & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003845 *puValue = pItem->val.uint64;
3846 } else {
3847 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3848 }
3849 break;
3850
3851 default:
3852 return QCBOR_ERR_UNEXPECTED_TYPE;
3853 }
3854 return QCBOR_SUCCESS;
3855}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003856
3857
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003858void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3859 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003860 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003861 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003862{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003863 if(pMe->uLastError != QCBOR_SUCCESS) {
3864 return;
3865 }
3866
Laurence Lundbladec4537442020-04-14 18:53:22 -07003867 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003868
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003869 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3870 if(uError) {
3871 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003872 return;
3873 }
3874
Laurence Lundbladea826c502020-05-10 21:07:00 -07003875 if(pItem) {
3876 *pItem = Item;
3877 }
3878
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003879 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003880}
3881
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003882
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003883void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3884{
3885 int64_t uValue;
3886 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, &uValue, pItem);
3887 if(pMe->uLastError != QCBOR_SUCCESS) {
3888 return;
3889 }
3890
3891 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3892 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3893 }
3894}
3895
3896void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3897{
3898 int64_t uValue;
3899 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, &uValue, pItem);
3900 if(pMe->uLastError != QCBOR_SUCCESS) {
3901 return;
3902 }
3903
3904 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3905 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3906 }
3907}
3908
3909void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3910{
3911 int64_t uValue;
3912 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, &uValue, pItem);
3913 if(pMe->uLastError != QCBOR_SUCCESS) {
3914 return;
3915 }
3916
3917 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3918 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3919 }
3920}
3921
3922
3923
3924
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003925void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3926 int64_t nLabel,
3927 uint32_t uOptions,
3928 uint64_t *puValue,
3929 QCBORItem *pItem)
3930{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003931 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003932 if(pMe->uLastError != QCBOR_SUCCESS) {
3933 return;
3934 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003935
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003936 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uOptions, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003937}
3938
3939
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003940void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003941 const char * szLabel,
3942 uint32_t uOptions,
3943 uint64_t *puValue,
3944 QCBORItem *pItem)
3945{
3946 if(pMe->uLastError != QCBOR_SUCCESS) {
3947 return;
3948 }
3949
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003950 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003951 if(pMe->uLastError != QCBOR_SUCCESS) {
3952 return;
3953 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003954
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003955 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uOptions, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003956}
3957
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003958/*
3959 Public function, see header qcbor/qcbor_decode.h file
3960*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003961static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3962{
3963 QCBORError uErr;
3964
3965 switch(pItem->uDataType) {
3966
3967 case QCBOR_TYPE_POSBIGNUM:
3968 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3969 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3970 } else {
3971 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3972 }
3973 break;
3974
3975 case QCBOR_TYPE_NEGBIGNUM:
3976 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3977 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3978 } else {
3979 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3980 }
3981 break;
3982
3983#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3984
3985 case QCBOR_TYPE_DECIMAL_FRACTION:
3986 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3987 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3988 pItem->val.expAndMantissa.nExponent,
3989 puValue,
3990 Exponentitate10);
3991 } else {
3992 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3993 }
3994 break;
3995
3996 case QCBOR_TYPE_BIGFLOAT:
3997 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3998 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3999 pItem->val.expAndMantissa.nExponent,
4000 puValue,
4001 Exponentitate2);
4002 } else {
4003 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4004 }
4005 break;
4006
4007 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4008 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4009 // TODO: Would be better to convert to unsigned
4010 int64_t nMantissa;
4011 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4012 if(uErr != QCBOR_SUCCESS) {
4013 return uErr;
4014 }
4015 return ExponentitateNU(nMantissa,
4016 pItem->val.expAndMantissa.nExponent,
4017 puValue,
4018 Exponentitate10);
4019 } else {
4020 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4021 }
4022 break;
4023
4024 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4025 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4026 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4027 } else {
4028 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4029 }
4030 break;
4031
4032 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4033 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4034 // TODO: Would be better to convert to unsigned
4035 int64_t nMantissa;
4036 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4037 if(uErr != QCBOR_SUCCESS) {
4038 return uErr;
4039 }
4040 return ExponentitateNU(nMantissa,
4041 pItem->val.expAndMantissa.nExponent,
4042 puValue,
4043 Exponentitate2);
4044 } else {
4045 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4046 }
4047 break;
4048
4049 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4050 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4051 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4052 } else {
4053 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4054 }
4055 break;
4056#endif
4057 default:
4058 return QCBOR_ERR_UNEXPECTED_TYPE;
4059 }
4060}
4061
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004062/*
4063 Public function, see header qcbor/qcbor_decode.h file
4064*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004065void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004066{
4067 QCBORItem Item;
4068
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004069 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004070
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004071 if(pMe->uLastError == QCBOR_SUCCESS) {
4072 // The above conversion succeeded
4073 return;
4074 }
4075
4076 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4077 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004078 return;
4079 }
4080
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004081 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004082}
4083
Laurence Lundbladec4537442020-04-14 18:53:22 -07004084
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004085/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004086 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004087*/
4088void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
4089{
4090 QCBORItem Item;
4091
4092 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
4093
4094 if(pMe->uLastError == QCBOR_SUCCESS) {
4095 // The above conversion succeeded
4096 return;
4097 }
4098
4099 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4100 // The above conversion failed in a way that code below can't correct
4101 return;
4102 }
4103
4104 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4105}
4106
4107
4108/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004109 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004110*/
4111void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
4112{
4113 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004114 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004115
4116 if(pMe->uLastError == QCBOR_SUCCESS) {
4117 // The above conversion succeeded
4118 return;
4119 }
4120
4121 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4122 // The above conversion failed in a way that code below can't correct
4123 return;
4124 }
4125
4126 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4127}
4128
4129
4130static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
4131{
4132 switch(pItem->uDataType) {
4133 // TODO: float when ifdefs are set
4134 case QCBOR_TYPE_DOUBLE:
4135 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4136 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4137 *pdValue = pItem->val.dfnum;
4138 } else {
4139 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4140 }
4141 }
4142 break;
4143
4144 case QCBOR_TYPE_INT64:
4145 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
4146 // TODO: how does this work?
4147 *pdValue = (double)pItem->val.int64;
4148
4149 } else {
4150 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4151 }
4152 break;
4153
4154 case QCBOR_TYPE_UINT64:
4155 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
4156 *pdValue = (double)pItem->val.uint64;
4157 } else {
4158 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4159 }
4160 break;
4161
4162 default:
4163 return QCBOR_ERR_UNEXPECTED_TYPE;
4164 }
4165
4166 return QCBOR_SUCCESS;
4167}
4168
4169
4170
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004171void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
4172 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004173 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004174 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004175{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004176 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004177 return;
4178 }
4179
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004180 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004181
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004182 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004183 if(uError) {
4184 pMe->uLastError = (uint8_t)uError;
4185 return;
4186 }
4187
4188 if(pItem) {
4189 *pItem = Item;
4190 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004191
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004192 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004193}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004194
Laurence Lundbladec4537442020-04-14 18:53:22 -07004195
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004196void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4197 int64_t nLabel,
4198 uint32_t uOptions,
4199 double *pdValue,
4200 QCBORItem *pItem)
4201{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004202 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004203 if(pMe->uLastError != QCBOR_SUCCESS) {
4204 return;
4205 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004206
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004207 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uOptions, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004208}
4209
4210void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4211 const char * szLabel,
4212 uint32_t uOptions,
4213 double *pdValue,
4214 QCBORItem *pItem)
4215{
4216 if(pMe->uLastError != QCBOR_SUCCESS) {
4217 return;
4218 }
4219
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004220 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004221 if(pMe->uLastError != QCBOR_SUCCESS) {
4222 return;
4223 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004224
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004225 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uOptions, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004226}
4227
4228
4229
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004230static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4231{
4232 double dResult;
4233
4234 dResult = 0.0;
4235 const uint8_t *pByte = BigNum.ptr;
4236 size_t uLen = BigNum.len;
4237 /* This will overflow and become the float value INFINITY if the number
4238 is too large to fit. No error will be logged.
4239 TODO: should an error be logged? */
4240 while(uLen--) {
4241 dResult = (dResult * 256.0) + (double)*pByte++;
4242 }
4243
4244 return dResult;
4245}
4246
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004247static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004248{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004249 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004250 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4251
4252 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004253 switch(pItem->uDataType) {
4254 // TODO: type float
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004255
4256#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004257 case QCBOR_TYPE_DECIMAL_FRACTION:
4258 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4259 // TODO: rounding and overflow errors
4260 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4261 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4262 } else {
4263 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4264 }
4265 break;
4266
4267 case QCBOR_TYPE_BIGFLOAT:
4268 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
4269 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4270 exp2((double)pItem->val.expAndMantissa.nExponent);
4271 } else {
4272 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4273 }
4274 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004275#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004276
4277 case QCBOR_TYPE_POSBIGNUM:
4278 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
4279 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4280 } else {
4281 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4282 }
4283 break;
4284
4285 case QCBOR_TYPE_NEGBIGNUM:
4286 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004287 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004288 } else {
4289 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4290 }
4291 break;
4292
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004293#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004294 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4295 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4296 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4297 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4298 } else {
4299 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4300 }
4301 break;
4302
4303 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4304 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4305 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4306 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4307 } else {
4308 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4309 }
4310 break;
4311
4312 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4313 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
4314 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4315 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4316 } else {
4317 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4318 }
4319 break;
4320
4321 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4322 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004323 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004324 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4325 } else {
4326 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4327 }
4328 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004329#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4330
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004331
4332 default:
4333 return QCBOR_ERR_UNEXPECTED_TYPE;
4334 }
4335
4336 return QCBOR_SUCCESS;
4337}
4338
4339
4340/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004341 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004342*/
4343void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
4344{
4345
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004346 QCBORItem Item;
4347
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004348 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004349
4350 if(pMe->uLastError == QCBOR_SUCCESS) {
4351 // The above conversion succeeded
4352 return;
4353 }
4354
4355 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4356 // The above conversion failed in a way that code below can't correct
4357 return;
4358 }
4359
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004360 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004361}
4362
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004363
4364/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004365 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004366*/
4367void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
4368{
4369 QCBORItem Item;
4370
4371 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
4372
4373 if(pMe->uLastError == QCBOR_SUCCESS) {
4374 // The above conversion succeeded
4375 return;
4376 }
4377
4378 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4379 // The above conversion failed in a way that code below can't correct
4380 return;
4381 }
4382
4383 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4384}
4385
4386
4387/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004388 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004389*/
4390void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
4391{
4392 QCBORItem Item;
4393 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
4394
4395 if(pMe->uLastError == QCBOR_SUCCESS) {
4396 // The above conversion succeeded
4397 return;
4398 }
4399
4400 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4401 // The above conversion failed in a way that code below can't correct
4402 return;
4403 }
4404
4405 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4406}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004407
4408
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004409#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004410static void ProcessDecimalFraction(QCBORDecodeContext *pMe,
4411 uint8_t uTagRequirement,
4412 QCBORItem *pItem,
4413 int64_t *pnMantissa,
4414 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004415{
4416 QCBORError uErr;
4417
4418 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004419
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004420 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4421 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4422 return;
4423 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004424 /* The decimal fraction was untagged so it shows up as an
4425 array at this point. We are called to interpret it
4426 as a decimal fraction, so do protocol decoding. If
4427 it was tagged, iw would shouw up here with the
4428 QCBOR_TYPE_DECIMAL_FRACTION or such. */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004429 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4430 if(uErr != QCBOR_SUCCESS) {
4431 pMe->uLastError = (uint8_t)uErr;
4432 return;
4433 }
4434 }
4435
4436 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4437 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4438 return;
4439 }
4440
4441 switch (pItem->uDataType) {
4442
4443 case QCBOR_TYPE_DECIMAL_FRACTION:
4444 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4445 *pnExponent = pItem->val.expAndMantissa.nExponent;
4446 break;
4447
4448 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4449 *pnExponent = pItem->val.expAndMantissa.nExponent;
4450
4451 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4452 if(uErr != QCBOR_SUCCESS) {
4453 pMe->uLastError = (uint8_t)uErr;
4454 }
4455 break;
4456
4457 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4458 *pnExponent = pItem->val.expAndMantissa.nExponent;
4459
4460 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4461 if(uErr != QCBOR_SUCCESS) {
4462 pMe->uLastError = (uint8_t)uErr;
4463 }
4464 break;
4465
4466 default:
4467 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4468 }
4469}
4470
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004471
4472void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
4473 uint8_t uTagRequirement,
4474 int64_t *pnMantissa,
4475 int64_t *pnExponent)
4476{
4477 if(pMe->uLastError != QCBOR_SUCCESS) {
4478 return;
4479 }
4480
4481 QCBORItem Item;
4482 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4483 if(uError) {
4484 pMe->uLastError = (uint8_t)uError;
4485 return;
4486 }
4487
4488 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4489}
4490
4491
4492void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004493 uint8_t uTagRequirement,
4494 int64_t nLabel,
4495 int64_t *pnMantissa,
4496 int64_t *pnExponent)
4497{
4498 QCBORItem Item;
4499
4500 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004501 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004502}
4503
4504
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004505void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
4506 uint8_t uTagRequirement,
4507 const char *szLabel,
4508 int64_t *pnMantissa,
4509 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004510{
4511 QCBORItem Item;
4512
4513 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4514
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004515 ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004516}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004517#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004518
4519
4520UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4521{
4522 while(uInt & 0xff0000000000UL) {
4523 uInt = uInt << 8;
4524 };
4525
4526 UsefulOutBuf UOB;
4527
4528 UsefulOutBuf_Init(&UOB, Buffer);
4529
4530 while(uInt) {
4531 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56));
4532 uInt = uInt << 8;
4533 }
4534
4535 return UsefulOutBuf_OutUBuf(&UOB);
4536}
4537
4538
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004539#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4540
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004541static void ProcessDecimalFractionBig(QCBORDecodeContext *pMe,
4542 uint8_t uTagRequirement,
4543 QCBORItem *pItem,
4544 UsefulBuf BufferForMantissa,
4545 UsefulBufC *pMantissa,
4546 bool *pbIsNegative,
4547 int64_t *pnExponent)
4548{
4549
4550 const TagSpecification TagSpec = {uTagRequirement,
4551 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4552 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4553 };
4554
4555 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
4556 if(uErr != QCBOR_SUCCESS) {
4557 pMe->uLastError = (uint8_t)uErr;
4558 return;
4559 }
4560
4561 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
4562 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4563 if(uErr != QCBOR_SUCCESS) {
4564 pMe->uLastError = (uint8_t)uErr;
4565 return;
4566 }
4567 }
4568
4569 uint64_t uMantissa;
4570
4571 switch (pItem->uDataType) {
4572
4573 case QCBOR_TYPE_DECIMAL_FRACTION:
4574 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
4575 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
4576 *pbIsNegative = false;
4577 } else {
4578 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
4579 *pbIsNegative = true;
4580 }
4581 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
4582 *pnExponent = pItem->val.expAndMantissa.nExponent;
4583 break;
4584
4585 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4586 *pnExponent = pItem->val.expAndMantissa.nExponent;
4587 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4588 *pbIsNegative = false;
4589 break;
4590
4591 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4592 *pnExponent = pItem->val.expAndMantissa.nExponent;
4593 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4594 *pbIsNegative = true;
4595 break;
4596
4597 default:
4598 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4599 }
4600}
4601
4602
4603void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
4604 uint8_t uTagRequirement,
4605 UsefulBuf MantissaBuffer,
4606 UsefulBufC *pMantissa,
4607 bool *pbMantissaIsNegative,
4608 int64_t *pnExponent)
4609{
4610
4611 if(pMe->uLastError != QCBOR_SUCCESS) {
4612 return;
4613 }
4614
4615 QCBORItem Item;
4616 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4617 if(uError) {
4618 pMe->uLastError = (uint8_t)uError;
4619 return;
4620 }
4621
4622 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
4623
4624}
4625
4626void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
4627 uint8_t uTagRequirement,
4628 int64_t nLabel,
4629 UsefulBuf BufferForMantissa,
4630 UsefulBufC *pMantissa,
4631 bool *pbIsNegative,
4632 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004633{
4634 QCBORItem Item;
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004635
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004636 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004637 if(pMe->uLastError != QCBOR_SUCCESS) {
4638 return;
4639 }
4640
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004641 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
4642}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004643
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004644
4645void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
4646 uint8_t uTagRequirement,
4647 const char *szLabel,
4648 UsefulBuf BufferForMantissa,
4649 UsefulBufC *pMantissa,
4650 bool *pbIsNegative,
4651 int64_t *pnExponent)
4652{
4653 QCBORItem Item;
4654
4655 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4656 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004657 return;
4658 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004659
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004660 ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004661}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004662
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004663#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004664
4665/*
4666
4667 TODO: do something with this text
4668 The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...)
4669 formed by intermediate nodes (arrays and maps). The cursor for the traversal
4670 is the byte offset in the encoded input and a leaf counter for definite
4671 length maps and arrays. Indefinite length maps and arrays are handled
4672 by look ahead for the break.
4673
4674 The view presented to the caller has tags, labels and the chunks of
4675 indefinite length strings aggregated into one decorated data item.
4676
4677 The caller understands the nesting level in pre-order traversal by
4678 the fact that a data item that is a map or array is presented to
4679 the caller when it is first encountered in the pre-order traversal and that all data items are presented with its nesting level
4680 and the nesting level of the next item.
4681
4682 The caller traverse maps and arrays in a special mode that often more convenient
4683 that tracking by nesting level. When an array or map is expected or encountered
4684 the EnterMap or EnteryArray can be called.
4685
4686 When entering a map or array like this, the cursor points to the first
4687 item in the map or array. When exiting, it points to the item after
4688 the map or array, regardless of whether the items in the map or array were
4689 all traversed.
4690
4691 When in a map or array, the cursor functions as normal, but traversal
4692 cannot go past the end of the map or array that was entered. If this
4693 is attempted the QCBOR_ERR_NO_MORE_ITEMS error is returned. To
4694 go past the end of the map or array ExitMap() or ExitArray() must
4695 be called. It can be called any time regardless of the position
4696 of the cursor.
4697
4698 When a map is entered, a special function allows fetching data items
4699 by label. This call will traversal the whole map looking for the
4700 labeled item. The whole map is traversed so as to detect duplicates.
4701 This type of fetching items does not affect the normal traversal
4702 cursor.
4703
4704
4705 When a data item is presented to the caller, the nesting level of the data
4706 item is presented along with the nesting level of the item that would be
4707 next consumed.
4708 */