blob: aaa4a6d08b6872bfcfcc19e898c14f6102c0f1c0 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070035#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070036#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070037
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070038
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053039/*
40 This casts away the const-ness of a pointer, usually so it can be
41 freed or realloced.
42 */
43#define UNCONST_POINTER(ptr) ((void *)(ptr))
44
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070045
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070046
Laurence Lundblade02625d42020-06-25 14:41:41 -070047inline static bool
48// TODO: add more tests for QCBOR_TYPE_MAP_AS_ARRAY mode in qcbor_decode_tests.c
49QCBORItem_IsMapOrArray(const QCBORItem *pMe)
50{
51 const uint8_t uDataType = pMe->uDataType;
52 return uDataType == QCBOR_TYPE_MAP ||
53 uDataType == QCBOR_TYPE_ARRAY ||
54 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
55}
56
57inline static bool
58QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
59{
60 if(!QCBORItem_IsMapOrArray(pMe)){
61 return false;
62 }
63
64 if(pMe->val.uCount != 0) {
65 return false;
66 }
67 return true;
68}
69
70inline static bool
71QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
72{
73 if(!QCBORItem_IsMapOrArray(pMe)){
74 return false;
75 }
76
77 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
78 return false;
79 }
80 return true;
81}
82
83
Laurence Lundbladeee851742020-01-08 08:37:05 -080084/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070085 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080086 ===========================================================================*/
87
Laurence Lundblade9c905e82020-04-25 11:31:38 -070088/*
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070089 See commecnts about and typedef of QCBORDecodeNesting in qcbor_private.h, the data structure
90 all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -070091
Laurence Lundblade9c905e82020-04-25 11:31:38 -070092
Laurence Lundblade9c905e82020-04-25 11:31:38 -070093
Laurence Lundblade9c905e82020-04-25 11:31:38 -070094 */
95
Laurence Lundblade24d509a2020-06-06 18:43:15 -070096
97inline static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -070098DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -070099{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700100 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700101 /*
102 Limit in DecodeNesting_Descend against more than
103 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
104 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700105 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700106}
107
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700108
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700109inline static uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700110DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700111{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700112 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700113 /*
114 Limit in DecodeNesting_Descend against more than
115 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
116 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700117 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700118}
119
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700120
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700121static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700122DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700123{
124 return pNesting->pCurrentBounded->u.ma.uStartOffset;
125}
126
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700127
Laurence Lundblade085d7952020-07-24 10:26:30 -0700128static inline bool
129DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
130{
131 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
132 return true;
133 } else {
134 return false;
135 }
136}
137
138
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700139inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700140DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700141{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700142 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700143 return true;
144 } else {
145 return false;
146 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700147}
148
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700149
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700150inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700151DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700152{
153 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700154 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700155 return false;
156 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700157 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700158 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700159 return false;
160 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700161 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700162 return true;
163}
164
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700165
Laurence Lundblade642282a2020-06-23 12:00:33 -0700166inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700167DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700168{
169 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700170 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700171 return true;
172 }
173 return false;
174}
175
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700176
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700177inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700178{
179 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
180 return true;
181 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700182 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700183 return true;
184 }
185 return false;
186}
187
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700188
Laurence Lundblade085d7952020-07-24 10:26:30 -0700189inline static void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700190{
191 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700192 /*
193 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
194 larger than DecodeNesting_EnterBoundedMode which keeps it less than
195 uin32_t so the cast is safe.
196 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700197 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700198
199 if(bIsEmpty) {
200 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
201 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700202}
203
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700204
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700205inline static void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700206{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700207 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700208}
209
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700210
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700211inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700212DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700213{
214 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700215 // No bounded map or array or... set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700216 return false;
217 }
218 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700219 // Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700220 return false;
221 }
222 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700223 // Not at a bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700224 return false;
225 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700226 // Works for both definite and indefinite length maps/arrays
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700227 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700228 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700229 return false;
230 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700231 // All checks passed, got to the end of a map/array
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700232 return true;
233}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700234
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700235
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700236inline static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700237DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700238{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700239 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700240 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
241 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700242 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700243 return false;
244 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700245}
246
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700247
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700248inline static bool
249DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700250{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700251 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
252 return true;
253 } else {
254 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700255 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700256}
257
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700258
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700259inline static bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700260DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700261{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700262 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700263 return false;
264 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700265
266 if(pNesting->pCurrentBounded->uLevelType != uType) {
267 return false;
268 }
269
270 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700271}
272
Laurence Lundblade02625d42020-06-25 14:41:41 -0700273
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700274inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700275DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700276{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700277 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700278 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700279}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700280
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700281
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700282inline static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700283DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
284{
285 // Only call on a defnite length array / map
286 pNesting->pCurrent->u.ma.uCountCursor++;
287}
288
289
290inline static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700291DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
292{
293 pNesting->pCurrent--;
294}
295
Laurence Lundblade02625d42020-06-25 14:41:41 -0700296
297static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700298DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700299{
300 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700301 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700302 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
303 }
304
305 // The actual descend
306 pNesting->pCurrent++;
307
308 pNesting->pCurrent->uLevelType = uType;
309
310 return QCBOR_SUCCESS;
311}
312
313
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700314inline static QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700315DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700316{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700317 /*
318 Should only be called on map/array.
319
320 Have descended into this before this is called. The job here is
321 just to mark it in bounded mode.
322 */
Laurence Lundblade287b25c2020-08-06 13:48:42 -0700323 if(uOffset >= QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700324 return QCBOR_ERR_BUFFER_TOO_LARGE;
325 }
326
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700327 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700328
329 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700330
331 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700332}
333
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700334
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700335inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700336DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700337 uint8_t uQCBORType,
338 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700339{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700340 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700341
342 if(uCount == 0) {
343 // Nothing to do for empty definite lenth arrays. They are just are
344 // effectively the same as an item that is not a map or array
345 goto Done;
346 // Empty indefinite length maps and arrays are handled elsewhere
347 }
348
349 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700350 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
351 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
352 uError = QCBOR_ERR_ARRAY_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700353 goto Done;
354 }
355
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700356 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700357 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700358 goto Done;
359 }
360
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700361 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700362 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
363 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700364
365 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700366
367Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700368 return uError;;
369}
370
371
372static inline void
373DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
374{
375 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
376}
377
378
379static inline void
380DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
381{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700382 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700383 pNesting->pCurrentBounded--;
384 if(DecodeNesting_IsCurrentBounded(pNesting)) {
385 break;
386 }
387 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700388}
389
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700390static inline void
391DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
392{
393 pNesting->pCurrent = pNesting->pCurrentBounded;
394}
395
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700396
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700397inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700398DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
399 size_t uEndOffset,
400 size_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700401{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700402 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700403
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700404 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700405 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700406 goto Done;
407 }
408
Laurence Lundblade02625d42020-06-25 14:41:41 -0700409 // Fill in the new byte string level
410 // TODO: justify cast
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700411 pNesting->pCurrent->u.bs.uPreviousEndOffset = (uint32_t)uEndOffset;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700412 pNesting->pCurrent->u.bs.uEndOfBstr = (uint32_t)uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700413
Laurence Lundblade02625d42020-06-25 14:41:41 -0700414 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700415 pNesting->pCurrentBounded = pNesting->pCurrent;
416
417Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700418 return uError;;
419}
420
Laurence Lundbladed0304932020-06-27 10:59:38 -0700421
422static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700423DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700424{
425 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700426}
427
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700428
Laurence Lundbladeee851742020-01-08 08:37:05 -0800429inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700430DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700431{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700432 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700433 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
434 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700435}
436
437
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700438inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700439DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700440{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700441 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700442 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700443 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700444}
445
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700446
Laurence Lundblade02625d42020-06-25 14:41:41 -0700447static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700448DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700449{
450 *pNesting = *pSave;
451}
452
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700453
Laurence Lundblade02625d42020-06-25 14:41:41 -0700454static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700455DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700456{
457 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
458}
459
460
Laurence Lundblade02625d42020-06-25 14:41:41 -0700461static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700462DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700463{
464 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
465}
466
467
Laurence Lundblade02625d42020-06-25 14:41:41 -0700468#include <stdio.h>
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700469
470const char *TypeStr(uint8_t type)
471{
472 switch(type) {
473 case QCBOR_TYPE_MAP: return " map";
474 case QCBOR_TYPE_ARRAY: return "array";
475 case QCBOR_TYPE_BYTE_STRING: return " bstr";
476 default: return " --- ";
477 }
478}
479
480static char buf[20]; // Not thread safe, but that is OK
481const char *CountString(uint16_t uCount, uint16_t uTotal)
482{
483 if(uTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
484 strcpy(buf, "indefinite");
485 } else {
486 sprintf(buf, "%d/%d", uCount, uTotal);
487 }
488 return buf;
489}
490
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700491
Laurence Lundblade02625d42020-06-25 14:41:41 -0700492void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700493{
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700494#if 0
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700495 printf("---%s--%d/%d--\narrow is current bounded level\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700496 szName,
497 (uint32_t)pBuf->cursor,
498 (uint32_t)pBuf->UB.len);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700499
500 printf("Level Type Count Offsets \n");
Laurence Lundblade02625d42020-06-25 14:41:41 -0700501 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700502 if(&(pNesting->pLevels[i]) > pNesting->pCurrent) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700503 break;
504 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700505
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700506 printf("%2s %2d %s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700507 pNesting->pCurrentBounded == &(pNesting->pLevels[i]) ? "->": " ",
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700508 i,
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700509 TypeStr(pNesting->pLevels[i].uLevelType));
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700510
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700511 if(pNesting->pLevels[i].uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700512 printf(" %5d %5d",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700513 pNesting->pLevels[i].u.bs.uEndOfBstr,
514 pNesting->pLevels[i].u.bs.uPreviousEndOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700515
516 } else {
517 printf("%10.10s ",
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700518 CountString(pNesting->pLevels[i].u.ma.uCountCursor,
519 pNesting->pLevels[i].u.ma.uCountTotal));
520 if(pNesting->pLevels[i].u.ma.uStartOffset != UINT32_MAX) {
521 printf("Bounded start: %u",pNesting->pLevels[i].u.ma.uStartOffset);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700522 }
523 }
524
525 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700526 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700527 printf("\n");
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -0700528#endif
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700529}
530
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700531
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700532
Laurence Lundbladeee851742020-01-08 08:37:05 -0800533/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800534 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
535
536 The following four functions are pretty wrappers for invocation of
537 the string allocator supplied by the caller.
538
Laurence Lundbladeee851742020-01-08 08:37:05 -0800539 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800540
Laurence Lundbladeee851742020-01-08 08:37:05 -0800541static inline void
542StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800543{
544 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
545}
546
Laurence Lundbladeee851742020-01-08 08:37:05 -0800547// StringAllocator_Reallocate called with pMem NULL is
548// equal to StringAllocator_Allocate()
549static inline UsefulBuf
550StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
551 void *pMem,
552 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800553{
554 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
555}
556
Laurence Lundbladeee851742020-01-08 08:37:05 -0800557static inline UsefulBuf
558StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800559{
560 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
561}
562
Laurence Lundbladeee851742020-01-08 08:37:05 -0800563static inline void
564StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800565{
566 if(pMe->pfAllocator) {
567 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
568 }
569}
570
571
572
Laurence Lundbladeee851742020-01-08 08:37:05 -0800573/*===========================================================================
574 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700575
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800576 See qcbor/qcbor_decode.h for definition of the object
577 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800578 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700579/*
580 Public function, see header file
581 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800582void QCBORDecode_Init(QCBORDecodeContext *me,
583 UsefulBufC EncodedCBOR,
584 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700585{
586 memset(me, 0, sizeof(QCBORDecodeContext));
587 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800588 // Don't bother with error check on decode mode. If a bad value is
589 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700590 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700591 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700592 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700593 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700594 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700595}
596
597
598/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700599 Public function, see header file
600 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800601void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
602 QCBORStringAllocate pfAllocateFunction,
603 void *pAllocateContext,
604 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700605{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800606 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
607 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
608 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700609}
610
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800611
612/*
613 Public function, see header file
614 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700615void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800616 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700617{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700618 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700619 (void)pMe;
620 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700621}
622
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700623
624/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800625 This decodes the fundamental part of a CBOR data item, the type and
626 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800627
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700628 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800629
Laurence Lundbladeee851742020-01-08 08:37:05 -0800630 This does the network->host byte order conversion. The conversion
631 here also results in the conversion for floats in addition to that
632 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800633
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700634 This returns:
635 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800636
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800637 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800638 tags and floats and length for strings and arrays
639
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800640 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800641 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800642
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800643 The int type is preferred to uint8_t for some variables as this
644 avoids integer promotions, can reduce code size and makes
645 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800647inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
648 int *pnMajorType,
649 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800650 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700652 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800653
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700654 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800655 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800656
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700657 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800658 const int nTmpMajorType = nInitialByte >> 5;
659 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800660
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800661 // Where the number or argument accumulates
662 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800663
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800664 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700665 // Need to get 1,2,4 or 8 additional argument bytes. Map
666 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800667 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800668
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800669 // Loop getting all the bytes in the argument
670 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800671 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800672 // This shift and add gives the endian conversion
673 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
674 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800675 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800676 // The reserved and thus-far unused additional info values
677 nReturn = QCBOR_ERR_UNSUPPORTED;
678 goto Done;
679 } else {
680 // Less than 24, additional info is argument or 31, an indefinite length
681 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800682 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700683 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800684
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700685 if(UsefulInputBuf_GetError(pUInBuf)) {
686 nReturn = QCBOR_ERR_HIT_END;
687 goto Done;
688 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800689
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700690 // All successful if we got here.
691 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800692 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800693 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800694 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800695
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700696Done:
697 return nReturn;
698}
699
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800700
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800702 CBOR doesn't explicitly specify two's compliment for integers but all
703 CPUs use it these days and the test vectors in the RFC are so. All
704 integers in the CBOR structure are positive and the major type
705 indicates positive or negative. CBOR can express positive integers
706 up to 2^x - 1 where x is the number of bits and negative integers
707 down to 2^x. Note that negative numbers can be one more away from
708 zero than positive. Stdint, as far as I can tell, uses two's
709 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800710
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700711 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800712 used carefully here, and in particular why it isn't used in the interface.
713 Also see
714 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
715
716 Int is used for values that need less than 16-bits and would be subject
717 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700718 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800719inline static QCBORError
720DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700721{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700722 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800723
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
725 if (uNumber <= INT64_MAX) {
726 pDecodedItem->val.int64 = (int64_t)uNumber;
727 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800728
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700729 } else {
730 pDecodedItem->val.uint64 = uNumber;
731 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800732
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700733 }
734 } else {
735 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800736 // CBOR's representation of negative numbers lines up with the
737 // two-compliment representation. A negative integer has one
738 // more in range than a positive integer. INT64_MIN is
739 // equal to (-INT64_MAX) - 1.
740 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700741 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800742
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700743 } else {
744 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000745 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746 nReturn = QCBOR_ERR_INT_OVERFLOW;
747 }
748 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800749
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700750 return nReturn;
751}
752
753// Make sure #define value line up as DecodeSimple counts on this.
754#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
755#error QCBOR_TYPE_FALSE macro value wrong
756#endif
757
758#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
759#error QCBOR_TYPE_TRUE macro value wrong
760#endif
761
762#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
763#error QCBOR_TYPE_NULL macro value wrong
764#endif
765
766#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
767#error QCBOR_TYPE_UNDEF macro value wrong
768#endif
769
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700770#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
771#error QCBOR_TYPE_BREAK macro value wrong
772#endif
773
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700774#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
775#error QCBOR_TYPE_DOUBLE macro value wrong
776#endif
777
778#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
779#error QCBOR_TYPE_FLOAT macro value wrong
780#endif
781
782/*
783 Decode true, false, floats, break...
784 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800785inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800786DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700787{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700788 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800789
Laurence Lundbladeee851742020-01-08 08:37:05 -0800790 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800791 // above make sure uAdditionalInfo values line up with uDataType values.
792 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
793 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800794
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800795 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800796 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
797 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800798
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700799 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700800 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
801 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700802 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700803 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700804 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
805 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700806 break;
807 case DOUBLE_PREC_FLOAT:
808 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700809 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700810 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800811
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700812 case CBOR_SIMPLEV_FALSE: // 20
813 case CBOR_SIMPLEV_TRUE: // 21
814 case CBOR_SIMPLEV_NULL: // 22
815 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700816 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700817 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800818
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700819 case CBOR_SIMPLEV_ONEBYTE: // 24
820 if(uNumber <= CBOR_SIMPLE_BREAK) {
821 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700822 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700823 goto Done;
824 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800825 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700826 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800827
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700828 default: // 0-19
829 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800830 /*
831 DecodeTypeAndNumber will make uNumber equal to
832 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
833 safe because the 2, 4 and 8 byte lengths of uNumber are in
834 the double/float cases above
835 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700836 pDecodedItem->val.uSimple = (uint8_t)uNumber;
837 break;
838 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800839
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700840Done:
841 return nReturn;
842}
843
844
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700845/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530846 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700847 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800848inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
849 int nMajorType,
850 uint64_t uStrLen,
851 UsefulInputBuf *pUInBuf,
852 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700853{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700854 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800855
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800856 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
857 // This check makes the casts to size_t below safe.
858
859 // 4 bytes less than the largest sizeof() so this can be tested by
860 // putting a SIZE_MAX length in the CBOR test input (no one will
861 // care the limit on strings is 4 bytes shorter).
862 if(uStrLen > SIZE_MAX-4) {
863 nReturn = QCBOR_ERR_STRING_TOO_LONG;
864 goto Done;
865 }
866
867 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530868 if(UsefulBuf_IsNULLC(Bytes)) {
869 // Failed to get the bytes for this string item
870 nReturn = QCBOR_ERR_HIT_END;
871 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700872 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530873
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800874 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530875 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800876 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530877 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700878 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530879 goto Done;
880 }
881 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800882 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530883 } else {
884 // Normal case with no string allocator
885 pDecodedItem->val.string = Bytes;
886 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800887 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800888 // Cast because ternary operator causes promotion to integer
889 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
890 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800891
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530892Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700893 return nReturn;
894}
895
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700896
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800897
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700898
899
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700900
901
Laurence Lundbladeee851742020-01-08 08:37:05 -0800902// Make sure the constants align as this is assumed by
903// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700904#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
905#error QCBOR_TYPE_ARRAY value not lined up with major type
906#endif
907#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
908#error QCBOR_TYPE_MAP value not lined up with major type
909#endif
910
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700911/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800912 This gets a single data item and decodes it including preceding
913 optional tagging. This does not deal with arrays and maps and nesting
914 except to decode the data item introducing them. Arrays and maps are
915 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800916
Laurence Lundbladeee851742020-01-08 08:37:05 -0800917 Errors detected here include: an array that is too long to decode,
918 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700919 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800920static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
921 QCBORItem *pDecodedItem,
922 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700923{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700924 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800925
Laurence Lundbladeee851742020-01-08 08:37:05 -0800926 /*
927 Get the major type and the number. Number could be length of more
928 bytes or the value depending on the major type nAdditionalInfo is
929 an encoding of the length of the uNumber and is needed to decode
930 floats and doubles
931 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800932 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700933 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800934 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800935
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700936 memset(pDecodedItem, 0, sizeof(QCBORItem));
937
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800938 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800939
Laurence Lundbladeee851742020-01-08 08:37:05 -0800940 // Error out here if we got into trouble on the type and number. The
941 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700942 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700943 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700944 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800945
Laurence Lundbladeee851742020-01-08 08:37:05 -0800946 // At this point the major type and the value are valid. We've got
947 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800948 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700949 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
950 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800951 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700952 nReturn = QCBOR_ERR_BAD_INT;
953 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800954 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700955 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700956 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800957
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700958 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
959 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800960 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
961 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
962 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
963 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530964 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700965 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800966 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700967 }
968 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800969
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700970 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
971 case CBOR_MAJOR_TYPE_MAP: // Major type 5
972 // Record the number of items in the array or map
973 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
974 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
975 goto Done;
976 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800977 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700978 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700979 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800980 // type conversion OK because of check above
981 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700982 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800983 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800984 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
985 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700986 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800987
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700988 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800989 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700990 nReturn = QCBOR_ERR_BAD_INT;
991 } else {
992 pDecodedItem->val.uTagV = uNumber;
993 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
994 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700995 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800996
Laurence Lundbladeee851742020-01-08 08:37:05 -0800997 case CBOR_MAJOR_TYPE_SIMPLE:
998 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800999 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001000 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001001
Laurence Lundbladeee851742020-01-08 08:37:05 -08001002 default:
1003 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001004 nReturn = QCBOR_ERR_UNSUPPORTED;
1005 break;
1006 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001007
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001008Done:
1009 return nReturn;
1010}
1011
1012
1013
1014/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001015 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001016 individual chunk items together into one QCBORItem using the string
1017 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001018
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301019 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001020 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001021static inline QCBORError
1022GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001023{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001024 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001025
1026 // Get pointer to string allocator. First use is to pass it to
1027 // GetNext_Item() when option is set to allocate for *every* string.
1028 // Second use here is to allocate space to coallese indefinite
1029 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001030 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1031 &(me->StringAllocator) :
1032 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001033
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001034 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001035 nReturn = GetNext_Item(&(me->InBuf),
1036 pDecodedItem,
1037 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001038 if(nReturn) {
1039 goto Done;
1040 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001041
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001042 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301043 // code in this function from here down can be eliminated. Run tests, except
1044 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001045
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001046 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001047 const uint8_t uStringType = pDecodedItem->uDataType;
1048 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001049 goto Done; // no need to do any work here on non-string types
1050 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001051
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001052 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301053 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001054 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001055 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001056
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301057 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001058 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001059 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1060 goto Done;
1061 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001062
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001063 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001064 UsefulBufC FullString = NULLUsefulBufC;
1065
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001066 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001067 // Get item for next chunk
1068 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001069 // NULL string allocator passed here. Do not need to allocate
1070 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001071 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001072 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001073 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001074 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001075
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301076 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001077 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001078 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001079 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301080 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001081 break;
1082 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001083
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001084 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301085 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001086 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001087 if(StringChunkItem.uDataType != uStringType ||
1088 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001089 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001090 break;
1091 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001092
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301093 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001094 // The first time throurgh FullString.ptr is NULL and this is
1095 // equivalent to StringAllocator_Allocate()
1096 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1097 UNCONST_POINTER(FullString.ptr),
1098 FullString.len + StringChunkItem.val.string.len);
1099
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001100 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301101 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001102 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001103 break;
1104 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001105
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001106 // Copy new string chunk at the end of string so far.
1107 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001108 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001109
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001110 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1111 // Getting the item failed, clean up the allocated memory
1112 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001113 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001114
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001115Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001116 return nReturn;
1117}
1118
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001119
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001120static uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1121 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001122 return uTagVal;
1123 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001124 int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001125 return me->auMappedTags[x];
1126 }
1127}
1128
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001129/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001130 Gets all optional tag data items preceding a data item that is not an
1131 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001132 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001133static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001134GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001135{
Laurence Lundblade30816f22018-11-10 13:40:22 +07001136 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001137
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001138 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1139 CBOR_TAG_INVALID16,
1140 CBOR_TAG_INVALID16,
1141 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001142
Laurence Lundblade59289e52019-12-30 13:44:37 -08001143 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001144 for(;;) {
1145 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001146 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001147 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001148 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001149
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001150 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1151 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001152 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001153 break;
1154 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001155
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001156 // Is there room for the tag in the tags list?
1157 size_t uTagIndex;
1158 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001159 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001160 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001161 }
1162 }
1163 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001164 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001165 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001166
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001167 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001168 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001169 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001170 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001171 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001172 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001173 break;
1174 }
1175 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001176 // TODO: test this
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001177 break;
1178 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001179 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001180 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1181 // No room for the tag
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001182 // Should never happen as long as QCBOR_MAX_TAGS_PER_ITEM <= QCBOR_NUM_MAPPED_TAGS
1183 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001184 }
1185
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001186 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001187 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001188 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001189
1190 } else {
1191 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001192 }
1193 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001194
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001195Done:
1196 return nReturn;
1197}
1198
1199
1200/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001201 This layer takes care of map entries. It combines the label and data
1202 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001203 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001204static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001205GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001206{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001207 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001208 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001209 if(nReturn)
1210 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001211
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001212 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001213 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001214 goto Done;
1215 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001216
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001217 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1218 // In a map and caller wants maps decoded, not treated as arrays
1219
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001220 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001221 // If in a map and the right decoding mode, get the label
1222
Laurence Lundbladeee851742020-01-08 08:37:05 -08001223 // Save label in pDecodedItem and get the next which will
1224 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001225 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001226 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001227 if(nReturn)
1228 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001229
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301230 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001231
1232 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1233 // strings are always good labels
1234 pDecodedItem->label.string = LabelItem.val.string;
1235 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1236 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001237 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001238 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1239 goto Done;
1240 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1241 pDecodedItem->label.int64 = LabelItem.val.int64;
1242 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1243 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1244 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1245 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1246 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1247 pDecodedItem->label.string = LabelItem.val.string;
1248 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1249 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1250 } else {
1251 // label is not an int or a string. It is an arrray
1252 // or a float or such and this implementation doesn't handle that.
1253 // Also, tags on labels are ignored.
1254 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1255 goto Done;
1256 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001257 }
1258 } else {
1259 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001260 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1261 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1262 goto Done;
1263 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001264 // Decoding a map as an array
1265 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001266 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1267 // Cast is needed because of integer promotion
1268 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001269 }
1270 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001271
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001272Done:
1273 return nReturn;
1274}
1275
1276
Laurence Lundblade02625d42020-06-25 14:41:41 -07001277/*
1278 See if next item is a CBOR break. If it is, it is consumed,
1279 if not it is not consumed.
1280*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001281static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001282NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1283{
1284 *pbNextIsBreak = false;
1285 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001286 QCBORItem Peek;
1287 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1288 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1289 if(uReturn != QCBOR_SUCCESS) {
1290 return uReturn;
1291 }
1292 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001293 // It is not a break, rewind so it can be processed normally.
1294 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001295 } else {
1296 *pbNextIsBreak = true;
1297 }
1298 }
1299
1300 return QCBOR_SUCCESS;
1301}
1302
1303
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001304/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001305 An item was just consumed, now figure out if it was the
1306 end of an array or map that can be closed out. That
1307 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001308*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001309static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001310{
1311 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001312
Laurence Lundblade642282a2020-06-23 12:00:33 -07001313 /* This loops ascending nesting levels as long as there is ascending to do */
1314 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1315
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001316 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001317 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001318 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1319 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001320 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001321 break;
1322 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001323 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001324
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001325 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001326 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001327 bool bIsBreak = false;
1328 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1329 if(uReturn != QCBOR_SUCCESS) {
1330 goto Done;
1331 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001332
1333 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001334 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001335 break;
1336 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001337
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001338 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001339 /*
1340 Break occurred inside a bstr-wrapped CBOR or
1341 in the top level sequence. This is always an
1342 error because neither are an indefinte length
1343 map/array.
1344 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001345 uReturn = QCBOR_ERR_BAD_BREAK;
1346 goto Done;
1347 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07001348
Laurence Lundblade02625d42020-06-25 14:41:41 -07001349 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001350 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001351
Laurence Lundblade02625d42020-06-25 14:41:41 -07001352 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001353
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001354 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001355 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001356 /* 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 -07001357 if(bMarkEnd) {
1358 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001359 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001360
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001361 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001362 break;
1363 }
1364
1365 /* Finally, actually ascend one level. */
1366 DecodeNesting_Ascend(&(pMe->nesting));
1367 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001368
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001369 uReturn = QCBOR_SUCCESS;
1370
1371Done:
1372 return uReturn;
1373}
1374
1375
1376/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001377 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001378 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1379 indefinte length maps and arrays by looking at the item count or
1380 finding CBOR breaks. It detects the ends of the top-level sequence
1381 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001382 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001383static QCBORError
1384QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001385{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001386 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001387 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001388
Laurence Lundblade642282a2020-06-23 12:00:33 -07001389 /*
1390 If out of bytes to consume, it is either the end of the top-level
1391 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001392
Laurence Lundblade642282a2020-06-23 12:00:33 -07001393 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1394 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1395 CBOR is exited, the length is set back to the top-level's length
1396 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001397 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001398 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001399 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001400 goto Done;
1401 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001402
Laurence Lundblade642282a2020-06-23 12:00:33 -07001403 /*
1404 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001405 array. The check for the end of an indefinite length array is
1406 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001407 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001408 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001409 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001410 goto Done;
1411 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001412
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001413 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001414 uReturn = GetNext_MapEntry(me, pDecodedItem);
1415 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001416 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001417 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301418
Laurence Lundblade642282a2020-06-23 12:00:33 -07001419 /*
1420 Breaks ending arrays/maps are always processed at the end of this
1421 function. They should never show up here.
1422 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301423 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001424 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301425 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301426 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001427
Laurence Lundblade642282a2020-06-23 12:00:33 -07001428 /*
1429 Record the nesting level for this data item before processing any
1430 of decrementing and descending.
1431 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001432 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001433
Laurence Lundblade642282a2020-06-23 12:00:33 -07001434
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001435 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001436 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001437 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001438 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001439
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001440 Empty indefinite length maps and arrays are descended into, but then ascended out
Laurence Lundblade02625d42020-06-25 14:41:41 -07001441 of in the next chunk of code.
1442
1443 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001444 encloses them so a decrement needs to be done for them too, but
1445 that is done only when all the items in them have been
1446 processed, not when they are opened with the exception of an
1447 empty map or array.
1448 */
1449 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1450 pDecodedItem->uDataType,
1451 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001452 if(uReturn != QCBOR_SUCCESS) {
1453 goto Done;
1454 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001455 }
1456
Laurence Lundblade02625d42020-06-25 14:41:41 -07001457 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1458 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1459 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001460 /*
1461 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001462 - A non-aggregate like an integer or string
1463 - An empty definite length map or array
1464 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001465
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001466 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001467 definite length map/array and break detection for an indefinite
1468 length map/array. If the end of the map/array was reached, then
1469 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001470 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001471 uReturn = NestLevelAscender(me, true);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001472 if(uReturn) {
1473 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001474 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301475 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001476
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001477 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001478 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001479 Tell the caller what level is next. This tells them what
1480 maps/arrays were closed out and makes it possible for them to
1481 reconstruct the tree with just the information returned in
1482 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001483 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001484 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001485 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001486 pDecodedItem->uNextNestLevel = 0;
1487 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001488 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001489 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001490
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001491Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001492 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001493 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001494 memset(pDecodedItem, 0, sizeof(QCBORItem));
1495 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001496 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001497}
1498
1499
Laurence Lundblade59289e52019-12-30 13:44:37 -08001500/*
1501 Mostly just assign the right data type for the date string.
1502 */
1503inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1504{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001505 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1506 return QCBOR_ERR_BAD_OPT_TAG;
1507 }
1508
1509 const UsefulBufC Temp = pDecodedItem->val.string;
1510 pDecodedItem->val.dateString = Temp;
1511 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1512 return QCBOR_SUCCESS;
1513}
1514
1515
1516/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001517 The epoch formatted date. Turns lots of different forms of encoding
1518 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001519 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001520static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001521{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001522 QCBORError nReturn = QCBOR_SUCCESS;
1523
1524 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1525
1526 switch (pDecodedItem->uDataType) {
1527
1528 case QCBOR_TYPE_INT64:
1529 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1530 break;
1531
1532 case QCBOR_TYPE_UINT64:
1533 if(pDecodedItem->val.uint64 > INT64_MAX) {
1534 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1535 goto Done;
1536 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001537 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001538 break;
1539
1540 case QCBOR_TYPE_DOUBLE:
1541 {
1542 // This comparison needs to be done as a float before
1543 // conversion to an int64_t to be able to detect doubles
1544 // that are too large to fit into an int64_t. A double
1545 // has 52 bits of preceision. An int64_t has 63. Casting
1546 // INT64_MAX to a double actually causes a round up which
1547 // is bad and wrong for the comparison because it will
1548 // allow conversion of doubles that can't fit into a
1549 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1550 // the cutoff point as if that rounds up in conversion to
1551 // double it will still be less than INT64_MAX. 0x7ff is
1552 // picked because it has 11 bits set.
1553 //
1554 // INT64_MAX seconds is on the order of 10 billion years,
1555 // and the earth is less than 5 billion years old, so for
1556 // most uses this conversion error won't occur even though
1557 // doubles can go much larger.
1558 //
1559 // Without the 0x7ff there is a ~30 minute range of time
1560 // values 10 billion years in the past and in the future
1561 // where this this code would go wrong.
1562 const double d = pDecodedItem->val.dfnum;
1563 if(d > (double)(INT64_MAX - 0x7ff)) {
1564 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1565 goto Done;
1566 }
1567 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1568 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1569 }
1570 break;
1571
1572 default:
1573 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1574 goto Done;
1575 }
1576 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1577
1578Done:
1579 return nReturn;
1580}
1581
1582
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001583/*
1584 Mostly just assign the right data type for the bignum.
1585 */
1586inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1587{
1588 // Stack Use: UsefulBuf 1 -- 16
1589 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1590 return QCBOR_ERR_BAD_OPT_TAG;
1591 }
1592 const UsefulBufC Temp = pDecodedItem->val.string;
1593 pDecodedItem->val.bigNum = Temp;
1594 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1595 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1596 : QCBOR_TYPE_NEGBIGNUM);
1597 return QCBOR_SUCCESS;
1598}
1599
1600
Laurence Lundblade59289e52019-12-30 13:44:37 -08001601#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1602/*
1603 Decode decimal fractions and big floats.
1604
1605 When called pDecodedItem must be the array that is tagged as a big
1606 float or decimal fraction, the array that has the two members, the
1607 exponent and mantissa.
1608
1609 This will fetch and decode the exponent and mantissa and put the
1610 result back into pDecodedItem.
1611 */
1612inline static QCBORError
1613QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1614{
1615 QCBORError nReturn;
1616
1617 // --- Make sure it is an array; track nesting level of members ---
1618 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1619 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1620 goto Done;
1621 }
1622
1623 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001624 // definite length arrays, but not for indefnite. Instead remember
1625 // the nesting level the two integers must be at, which is one
1626 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001627 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1628
1629 // --- Is it a decimal fraction or a bigfloat? ---
1630 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1631 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1632
1633 // --- Get the exponent ---
1634 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001635 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001636 if(nReturn != QCBOR_SUCCESS) {
1637 goto Done;
1638 }
1639 if(exponentItem.uNestingLevel != nNestLevel) {
1640 // Array is empty or a map/array encountered when expecting an int
1641 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1642 goto Done;
1643 }
1644 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1645 // Data arriving as an unsigned int < INT64_MAX has been converted
1646 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1647 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1648 // will be too large for this to handle and thus an error that will
1649 // get handled in the next else.
1650 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1651 } else {
1652 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1653 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1654 goto Done;
1655 }
1656
1657 // --- Get the mantissa ---
1658 QCBORItem mantissaItem;
1659 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1660 if(nReturn != QCBOR_SUCCESS) {
1661 goto Done;
1662 }
1663 if(mantissaItem.uNestingLevel != nNestLevel) {
1664 // Mantissa missing or map/array encountered when expecting number
1665 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1666 goto Done;
1667 }
1668 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1669 // Data arriving as an unsigned int < INT64_MAX has been converted
1670 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1671 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1672 // will be too large for this to handle and thus an error that
1673 // will get handled in an else below.
1674 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1675 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1676 // Got a good big num mantissa
1677 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1678 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001679 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1680 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1681 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001682 } else {
1683 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1684 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1685 goto Done;
1686 }
1687
1688 // --- Check that array only has the two numbers ---
1689 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001690 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001691 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1692 goto Done;
1693 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07001694 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel; // TODO: make sure this is right
Laurence Lundblade59289e52019-12-30 13:44:37 -08001695
1696Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001697 return nReturn;
1698}
1699#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1700
1701
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001702inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1703{
1704 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1705 return QCBOR_ERR_BAD_OPT_TAG;
1706 }
1707 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1708 return QCBOR_SUCCESS;
1709}
1710
1711
1712inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1713{
1714 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1715 return QCBOR_ERR_BAD_OPT_TAG;
1716 }
1717 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1718 return QCBOR_SUCCESS;
1719}
1720
1721
1722inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1723{
1724 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1725 return QCBOR_ERR_BAD_OPT_TAG;
1726 }
1727 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1728 return QCBOR_SUCCESS;
1729}
1730
1731
1732inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1733{
1734 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1735 return QCBOR_ERR_BAD_OPT_TAG;
1736 }
1737 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1738 return QCBOR_SUCCESS;
1739}
1740
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001741
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 Lundblade4a21be12020-08-05 12:48:33 -07001761
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001762inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1763{
1764 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1765 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001766 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001767 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1768 } else {
1769 return QCBOR_ERR_BAD_OPT_TAG;
1770 }
1771 return QCBOR_SUCCESS;
1772}
1773
1774
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001775inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1776{
1777 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1778 return QCBOR_ERR_BAD_OPT_TAG;
1779 }
1780 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1781 return QCBOR_SUCCESS;
1782}
1783
1784
Laurence Lundblade59289e52019-12-30 13:44:37 -08001785/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001786 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001787 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001788QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001789QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001790{
1791 QCBORError nReturn;
1792
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001793 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001794 if(nReturn != QCBOR_SUCCESS) {
1795 goto Done;
1796 }
1797
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001798 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1799 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001800
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001801 // Many of the functions here only just map a CBOR tag to
1802 // a QCBOR_TYPE for a string and could probably be
1803 // implemented with less object code. This implementation
1804 // of string types takes about 120 bytes of object code
1805 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001806 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001807 nReturn = DecodeDateString(pDecodedItem);
1808 break;
1809
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001810 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001811 nReturn = DecodeDateEpoch(pDecodedItem);
1812 break;
1813
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001814 case CBOR_TAG_POS_BIGNUM:
1815 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001816 nReturn = DecodeBigNum(pDecodedItem);
1817 break;
1818
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001819 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1820 case CBOR_TAG_DECIMAL_FRACTION:
1821 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001822 // For aggregate tagged types, what goes into pTags is only collected
1823 // from the surrounding data item, not the contents, so pTags is not
1824 // passed on here.
1825
1826 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1827 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001828 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001829
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001830 case CBOR_TAG_CBOR:
1831 nReturn = DecodeWrappedCBOR(pDecodedItem);
1832 break;
1833
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001834 case CBOR_TAG_CBOR_SEQUENCE:
1835 nReturn = DecodeWrappedCBORSequence(pDecodedItem);
1836 break;
1837
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001838 case CBOR_TAG_URI:
1839 nReturn = DecodeURI(pDecodedItem);
1840 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001841
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001842 case CBOR_TAG_B64URL:
1843 nReturn = DecodeB64URL(pDecodedItem);
1844 break;
1845
1846 case CBOR_TAG_B64:
1847 nReturn = DecodeB64(pDecodedItem);
1848 break;
1849
1850 case CBOR_TAG_MIME:
1851 case CBOR_TAG_BINARY_MIME:
1852 nReturn = DecodeMIME(pDecodedItem);
1853 break;
1854
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001855 case CBOR_TAG_REGEX:
1856 nReturn = DecodeRegex(pDecodedItem);
1857 break;
1858
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001859 case CBOR_TAG_BIN_UUID:
1860 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001861 break;
1862
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001863 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001864 // The end of the tag list or no tags
1865 // Successful exit from the loop.
1866 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001867
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001868 default:
1869 // A tag that is not understood
1870 // A successful exit from the loop
1871 goto Done;
1872
1873 }
1874 if(nReturn != QCBOR_SUCCESS) {
1875 goto Done;
1876 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001877 }
1878
1879Done:
1880 if(nReturn != QCBOR_SUCCESS) {
1881 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1882 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1883 }
1884 return nReturn;
1885}
1886
1887
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001888QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1889{
1890 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1891
1892 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1893
1894 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundblade78f7b932020-07-28 20:02:25 -07001895 // TODO: undo the level tracking (or don't do it)
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001896
1897 return uErr;
1898}
1899
1900
Laurence Lundblade59289e52019-12-30 13:44:37 -08001901/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001902 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001903 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001904QCBORError
1905QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1906 QCBORItem *pDecodedItem,
1907 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001908{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001909 QCBORError nReturn;
1910
1911 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1912 if(nReturn != QCBOR_SUCCESS) {
1913 return nReturn;
1914 }
1915
1916 if(pTags != NULL) {
1917 pTags->uNumUsed = 0;
1918 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001919 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001920 break;
1921 }
1922 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1923 return QCBOR_ERR_TOO_MANY_TAGS;
1924 }
1925 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1926 pTags->uNumUsed++;
1927 }
1928 }
1929
1930 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001931}
1932
1933
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001934/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301935 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301936 next one down. If a layer has no work to do for a particular item
1937 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001938
Laurence Lundblade59289e52019-12-30 13:44:37 -08001939 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1940 tagged data items, turning them into the local C representation.
1941 For the most simple it is just associating a QCBOR_TYPE with the data. For
1942 the complex ones that an aggregate of data items, there is some further
1943 decoding and a little bit of recursion.
1944
1945 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301946 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301947 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001948 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001949
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301950 - GetNext_MapEntry -- This handles the combining of two
1951 items, the label and the data, that make up a map entry.
1952 It only does work on maps. It combines the label and data
1953 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001954
Laurence Lundblade59289e52019-12-30 13:44:37 -08001955 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1956 tags into bit flags associated with the data item. No actual decoding
1957 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001958
Laurence Lundblade59289e52019-12-30 13:44:37 -08001959 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301960 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301961 string allocater to create contiguous space for the item. It
1962 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001963
Laurence Lundblade59289e52019-12-30 13:44:37 -08001964 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1965 atomic data item has a "major type", an integer "argument" and optionally
1966 some content. For text and byte strings, the content is the bytes
1967 that make up the string. These are the smallest data items that are
1968 considered to be well-formed. The content may also be other data items in
1969 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001970
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001971 Roughly this takes 300 bytes of stack for vars. Need to
1972 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001973
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301974 */
1975
1976
1977/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001978 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001979 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001980int QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001981 const QCBORItem *pItem,
1982 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001983{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001984 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001985 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001986 break;
1987 }
1988 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1989 return 1;
1990 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001991 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001992
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001993 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001994}
1995
1996
1997/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001998 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001999 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002000QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002001{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002002 QCBORError uReturn = me->uLastError;
2003
2004 if(uReturn != QCBOR_SUCCESS) {
2005 goto Done;
2006 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002007
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002008 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002009 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002010 uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002011 goto Done;
2012 }
2013
2014 // Error out if not all the bytes are consumed
2015 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002016 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002017 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002018
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002019Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302020 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002021 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002022 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002023
Laurence Lundblade085d7952020-07-24 10:26:30 -07002024 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002025}
2026
2027
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002028/*
2029Public function, see header qcbor/qcbor_decode.h file
2030*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002031uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2032 const QCBORItem *pItem,
2033 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002034{
2035 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
2036 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002037 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002038 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002039 }
2040}
2041
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002042
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002043/*
2044
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002045Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002046
Laurence Lundbladeee851742020-01-08 08:37:05 -08002047 - Hit end of input before it was expected while decoding type and
2048 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002049
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002050 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002051
Laurence Lundbladeee851742020-01-08 08:37:05 -08002052 - Hit end of input while decoding a text or byte string
2053 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002054
Laurence Lundbladeee851742020-01-08 08:37:05 -08002055 - Encountered conflicting tags -- e.g., an item is tagged both a date
2056 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002057
Laurence Lundbladeee851742020-01-08 08:37:05 -08002058 - Encontered an array or mapp that has too many items
2059 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002060
Laurence Lundbladeee851742020-01-08 08:37:05 -08002061 - Encountered array/map nesting that is too deep
2062 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002063
Laurence Lundbladeee851742020-01-08 08:37:05 -08002064 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2065 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002066
Laurence Lundbladeee851742020-01-08 08:37:05 -08002067 - The type of a map label is not a string or int
2068 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002069
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002070 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002071
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002072 */
2073
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002074
2075
Laurence Lundbladef6531662018-12-04 10:42:22 +09002076
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002077/* ===========================================================================
2078 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002079
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002080 This implements a simple sting allocator for indefinite length
2081 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2082 implements the function type QCBORStringAllocate and allows easy
2083 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002084
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002085 This particular allocator is built-in for convenience. The caller
2086 can implement their own. All of this following code will get
2087 dead-stripped if QCBORDecode_SetMemPool() is not called.
2088
2089 This is a very primitive memory allocator. It does not track
2090 individual allocations, only a high-water mark. A free or
2091 reallocation must be of the last chunk allocated.
2092
2093 The size of the pool and offset to free memory are packed into the
2094 first 8 bytes of the memory pool so we don't have to keep them in
2095 the decode context. Since the address of the pool may not be
2096 aligned, they have to be packed and unpacked as if they were
2097 serialized data of the wire or such.
2098
2099 The sizes packed in are uint32_t to be the same on all CPU types
2100 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002101 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002102
2103
Laurence Lundbladeee851742020-01-08 08:37:05 -08002104static inline int
2105MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002106{
2107 // Use of UsefulInputBuf is overkill, but it is convenient.
2108 UsefulInputBuf UIB;
2109
Laurence Lundbladeee851742020-01-08 08:37:05 -08002110 // Just assume the size here. It was checked during SetUp so
2111 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002112 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2113 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2114 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2115 return UsefulInputBuf_GetError(&UIB);
2116}
2117
2118
Laurence Lundbladeee851742020-01-08 08:37:05 -08002119static inline int
2120MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002121{
2122 // Use of UsefulOutBuf is overkill, but convenient. The
2123 // length check performed here is useful.
2124 UsefulOutBuf UOB;
2125
2126 UsefulOutBuf_Init(&UOB, Pool);
2127 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2128 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2129 return UsefulOutBuf_GetError(&UOB);
2130}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002131
2132
2133/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002134 Internal function for an allocation, reallocation free and destuct.
2135
2136 Having only one function rather than one each per mode saves space in
2137 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002138
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002139 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2140 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002141static UsefulBuf
2142MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002143{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002144 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002145
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002146 uint32_t uPoolSize;
2147 uint32_t uFreeOffset;
2148
2149 if(uNewSize > UINT32_MAX) {
2150 // This allocator is only good up to 4GB. This check should
2151 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2152 goto Done;
2153 }
2154 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2155
2156 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2157 goto Done;
2158 }
2159
2160 if(uNewSize) {
2161 if(pMem) {
2162 // REALLOCATION MODE
2163 // Calculate pointer to the end of the memory pool. It is
2164 // assumed that pPool + uPoolSize won't wrap around by
2165 // assuming the caller won't pass a pool buffer in that is
2166 // not in legitimate memory space.
2167 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2168
2169 // Check that the pointer for reallocation is in the range of the
2170 // pool. This also makes sure that pointer math further down
2171 // doesn't wrap under or over.
2172 if(pMem >= pPool && pMem < pPoolEnd) {
2173 // Offset to start of chunk for reallocation. This won't
2174 // wrap under because of check that pMem >= pPool. Cast
2175 // is safe because the pool is always less than UINT32_MAX
2176 // because of check in QCBORDecode_SetMemPool().
2177 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2178
2179 // Check to see if the allocation will fit. uPoolSize -
2180 // uMemOffset will not wrap under because of check that
2181 // pMem is in the range of the uPoolSize by check above.
2182 if(uNewSize <= uPoolSize - uMemOffset) {
2183 ReturnValue.ptr = pMem;
2184 ReturnValue.len = uNewSize;
2185
2186 // Addition won't wrap around over because uNewSize was
2187 // checked to be sure it is less than the pool size.
2188 uFreeOffset = uMemOffset + uNewSize32;
2189 }
2190 }
2191 } else {
2192 // ALLOCATION MODE
2193 // uPoolSize - uFreeOffset will not underflow because this
2194 // pool implementation makes sure uFreeOffset is always
2195 // smaller than uPoolSize through this check here and
2196 // reallocation case.
2197 if(uNewSize <= uPoolSize - uFreeOffset) {
2198 ReturnValue.len = uNewSize;
2199 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002200 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002201 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002202 }
2203 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002204 if(pMem) {
2205 // FREE MODE
2206 // Cast is safe because of limit on pool size in
2207 // QCBORDecode_SetMemPool()
2208 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2209 } else {
2210 // DESTRUCT MODE
2211 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002212 }
2213 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002214
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002215 UsefulBuf Pool = {pPool, uPoolSize};
2216 MemPool_Pack(Pool, uFreeOffset);
2217
2218Done:
2219 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002220}
2221
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002222
Laurence Lundbladef6531662018-12-04 10:42:22 +09002223/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002224 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002225 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002226QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2227 UsefulBuf Pool,
2228 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002229{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002230 // The pool size and free mem offset are packed into the beginning
2231 // of the pool memory. This compile time check make sure the
2232 // constant in the header is correct. This check should optimize
2233 // down to nothing.
2234 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002235 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002236 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002237
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002238 // The pool size and free offset packed in to the beginning of pool
2239 // memory are only 32-bits. This check will optimize out on 32-bit
2240 // machines.
2241 if(Pool.len > UINT32_MAX) {
2242 return QCBOR_ERR_BUFFER_TOO_LARGE;
2243 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002244
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002245 // This checks that the pool buffer given is big enough.
2246 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2247 return QCBOR_ERR_BUFFER_TOO_SMALL;
2248 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002249
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002250 pMe->StringAllocator.pfAllocator = MemPool_Function;
2251 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2252 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002253
Laurence Lundblade30816f22018-11-10 13:40:22 +07002254 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002255}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002256
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002257
2258
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002259
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002260
2261
2262/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002263 Consume an entire map or array (and do next to
2264 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002265 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002266static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002267ConsumeItem(QCBORDecodeContext *pMe,
2268 const QCBORItem *pItemToConsume,
2269 uint_fast8_t *puNextNestLevel)
2270{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002271 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002272 QCBORItem Item;
2273
Laurence Lundblade02625d42020-06-25 14:41:41 -07002274 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002275
Laurence Lundblade02625d42020-06-25 14:41:41 -07002276 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002277 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002278
Laurence Lundblade1341c592020-04-11 14:19:05 -07002279 /* This works for definite and indefinite length
2280 * maps and arrays by using the nesting level
2281 */
2282 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002283 uReturn = QCBORDecode_GetNext(pMe, &Item);
2284 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002285 goto Done;
2286 }
2287 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002288
Laurence Lundblade1341c592020-04-11 14:19:05 -07002289 if(puNextNestLevel != NULL) {
2290 *puNextNestLevel = Item.uNextNestLevel;
2291 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002292 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002293
Laurence Lundblade1341c592020-04-11 14:19:05 -07002294 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002295 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002296 if(puNextNestLevel != NULL) {
2297 /* Just pass the nesting level through */
2298 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2299 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002300 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002301 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002302
2303Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002304 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002305}
2306
2307
Laurence Lundblade1341c592020-04-11 14:19:05 -07002308/* Return true if the labels in Item1 and Item2 are the same.
2309 Works only for integer and string labels. Returns false
2310 for any other type. */
2311static inline bool
2312MatchLabel(QCBORItem Item1, QCBORItem Item2)
2313{
2314 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2315 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2316 return true;
2317 }
2318 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002319 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002320 return true;
2321 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002322 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002323 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2324 return true;
2325 }
2326 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2327 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2328 return true;
2329 }
2330 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002331
Laurence Lundblade1341c592020-04-11 14:19:05 -07002332 /* Other label types are never matched */
2333 return false;
2334}
2335
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002336
2337/*
2338 Returns true if Item1 and Item2 are the same type
2339 or if either are of QCBOR_TYPE_ANY.
2340 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002341static inline bool
2342MatchType(QCBORItem Item1, QCBORItem Item2)
2343{
2344 if(Item1.uDataType == Item2.uDataType) {
2345 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002346 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002347 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002348 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002349 return true;
2350 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002351 return false;
2352}
2353
2354
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002355/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002356 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002357
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002358 @param[in] pMe The decode context to search.
2359 @param[in,out] pItemArray The items to search for and the items found.
2360 @param[out] puOffset Byte offset of last item matched.
2361 @param[in] pCBContext Context for the not-found item call back.
2362 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002363
2364 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2365
2366 @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.
2367
2368 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2369
2370 @retval Also errors returned by QCBORDecode_GetNext().
2371
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002372 On input pItemArray contains a list of labels and data types
2373 of items to be found.
2374
2375 On output the fully retrieved items are filled in with
2376 values and such. The label was matched, so it never changes.
2377
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002378 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002379 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002380static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002381MapSearch(QCBORDecodeContext *pMe,
2382 QCBORItem *pItemArray,
2383 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002384 void *pCBContext,
2385 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002386{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002387 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002388 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002389
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002390 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002391 uReturn = pMe->uLastError;
2392 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002393 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002394
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002395 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002396 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2397 /* QCBOR_TYPE_NONE as first item indicates just looking
2398 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002399 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2400 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002401 }
2402
Laurence Lundblade085d7952020-07-24 10:26:30 -07002403 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2404 // It is an empty bounded array or map
2405 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2406 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002407 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002408 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002409 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002410 // Nothing is ever found in an empty array or map. All items
2411 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002412 uReturn = QCBOR_SUCCESS;
2413 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002414 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002415 }
2416
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002417 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002418 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2419
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002420 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002421 UsefulInputBuf_Seek(&(pMe->InBuf),
2422 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002423
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002424 /*
2425 Loop over all the items in the map. They could be
2426 deeply nested and this should handle both definite
2427 and indefinite length maps and arrays, so this
2428 adds some complexity.
2429 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002430 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002431 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002432 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002433 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002434 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002435
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002436 /* Get the item */
2437 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002438 uReturn = QCBORDecode_GetNext(pMe, &Item);
2439 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002440 /* Got non-well-formed CBOR */
2441 goto Done;
2442 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002443
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002444 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002445 bool bMatched = false;
2446 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2447 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002448 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002449 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2450 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002451 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002452 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002453 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002454 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002455 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002456 goto Done;
2457 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002458
Laurence Lundblade1341c592020-04-11 14:19:05 -07002459 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002460 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002461 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002462 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002463 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002464 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002465 bMatched = true;
2466 }
2467 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002468
2469
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002470 if(!bMatched && pfCallback != NULL) {
2471 /*
2472 Call the callback on unmatched labels.
2473 (It is tempting to do duplicate detection here, but that would
2474 require dynamic memory allocation because the number of labels
2475 that might be encountered is unbounded.)
2476 */
2477 uReturn = (*pfCallback)(pCBContext, &Item);
2478 if(uReturn != QCBOR_SUCCESS) {
2479 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002480 }
2481 }
2482
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002483 /*
2484 Consume the item whether matched or not. This
2485 does the work of traversing maps and array and
2486 everything in them. In this loop only the
2487 items at the current nesting level are examined
2488 to match the labels.
2489 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002490 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2491 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002492 goto Done;
2493 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002494
2495 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002496
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002497 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002498
2499 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002500 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2501 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002502
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002503 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002504 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2505
2506 Done2:
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002507 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
2508 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002509 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002510 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002511 }
2512 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002513
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002514 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002515}
2516
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002517
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002518/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002519 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002520*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002521void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2522 int64_t nLabel,
2523 uint8_t uQcborType,
2524 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002525{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002526 if(pMe->uLastError != QCBOR_SUCCESS) {
2527 return;
2528 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002529
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002530 QCBORItem OneItemSeach[2];
2531 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2532 OneItemSeach[0].label.int64 = nLabel;
2533 OneItemSeach[0].uDataType = uQcborType;
2534 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002535
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002536 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2537 if(uReturn != QCBOR_SUCCESS) {
2538 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002539 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002540 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002541 uReturn = QCBOR_ERR_NOT_FOUND;
2542 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002543 }
2544
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002545 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002546
2547 Done:
2548 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002549}
2550
2551
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002552/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002553 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002554*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002555void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2556 const char *szLabel,
2557 uint8_t uQcborType,
2558 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002559{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002560 if(pMe->uLastError != QCBOR_SUCCESS) {
2561 return;
2562 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002563
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002564 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002565 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2566 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2567 OneItemSeach[0].uDataType = uQcborType;
2568 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002569
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002570 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2571 if(uReturn != QCBOR_SUCCESS) {
2572 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002573 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002574 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002575 uReturn = QCBOR_ERR_NOT_FOUND;
2576 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002577 }
2578
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002579 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002580
2581Done:
2582 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002583}
2584
2585
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002586
2587static QCBORError CheckTypeList(uint8_t uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
2588{
2589 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2590 if(uDataType == puTypeList[i]) {
2591 return QCBOR_SUCCESS;
2592 }
2593 }
2594 return QCBOR_ERR_UNEXPECTED_TYPE;
2595}
2596
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002597
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002598/**
2599 @param[in] TagSpec Specification for matching tags.
2600 @param[in] uDataType A QCBOR data type
2601
2602 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2603 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2604
2605 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2606 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002607static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002608{
Laurence Lundbladef9175a92020-07-30 21:35:45 -07002609 if(TagSpec.uTagRequirement == QCBOR_TAG_REQUIREMENT_MATCH_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002610 // Must match the tag and only the tag
2611 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002612 }
2613
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002614 QCBORError uReturn = CheckTypeList(uDataType, TagSpec.uAllowedContentTypes);
2615 if(uReturn == QCBOR_SUCCESS) {
2616 return QCBOR_SUCCESS;
2617 }
2618
Laurence Lundbladef9175a92020-07-30 21:35:45 -07002619 if(TagSpec.uTagRequirement == QCBOR_TAG_REQUIREMENT_NO_TAG) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002620 /* Must match the content type and only the content type.
2621 There was no match just above so it is a fail. */
2622 return QCBOR_ERR_UNEXPECTED_TYPE;
2623 }
2624
2625 /* If here it can match either the tag or the content
2626 and it hasn't matched the content, so the end
2627 result is whether it matches the tag. This is
2628 also the case that the CBOR standard discourages. */
2629
2630 return CheckTypeList(uDataType, TagSpec.uTaggedTypes);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002631}
2632
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002633
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002634// Semi-private
2635// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002636void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2637 int64_t nLabel,
2638 TagSpecification TagSpec,
2639 QCBORItem *pItem)
2640{
2641 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2642 if(pMe->uLastError != QCBOR_SUCCESS) {
2643 return;
2644 }
2645
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002646 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002647}
2648
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002649// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002650void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2651 const char *szLabel,
2652 TagSpecification TagSpec,
2653 QCBORItem *pItem)
2654{
2655 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2656 if(pMe->uLastError != QCBOR_SUCCESS) {
2657 return;
2658 }
2659
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002660 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002661}
2662
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002663// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002664void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2665 int64_t nLabel,
2666 TagSpecification TagSpec,
2667 UsefulBufC *pString)
2668{
2669 QCBORItem Item;
2670 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2671 if(pMe->uLastError == QCBOR_SUCCESS) {
2672 *pString = Item.val.string;
2673 }
2674}
2675
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002676// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002677void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2678 const char * szLabel,
2679 TagSpecification TagSpec,
2680 UsefulBufC *pString)
2681{
2682 QCBORItem Item;
2683 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2684 if(pMe->uLastError == QCBOR_SUCCESS) {
2685 *pString = Item.val.string;
2686 }
2687}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002688
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002689/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002690 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002691*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002692QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2693{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002694 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002695}
2696
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002697/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002698 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002699*/
2700QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2701 QCBORItem *pItemList,
2702 void *pCallbackCtx,
2703 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002704{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002705 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002706}
2707
2708
Laurence Lundblade34691b92020-05-18 22:25:25 -07002709static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002710{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002711 // TODO: check that only one item is in pSearch?
Laurence Lundblade34691b92020-05-18 22:25:25 -07002712 if(pMe->uLastError != QCBOR_SUCCESS) {
2713 // Already in error state; do nothing.
2714 return;
2715 }
2716
2717 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002718 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002719 if(pMe->uLastError != QCBOR_SUCCESS) {
2720 return;
2721 }
2722
Laurence Lundblade085d7952020-07-24 10:26:30 -07002723 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
2724 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
2725 return;
2726 }
2727
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002728 /* Need to get the current pre-order nesting level and cursor to be
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002729 at the map/array about to be entered.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002730
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002731 Also need the current map nesting level and start cursor to
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002732 be at the right place.
2733
2734 The UsefulInBuf offset could be anywhere, so no assumption is
2735 made about it.
2736
2737 No assumption is made about the pre-order nesting level either.
2738
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002739 However the bounded mode nesting level is assumed to be one above
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002740 the map level that is being entered.
2741 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002742 /* Seek to the data item that is the map or array */
2743 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002744
2745 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002746
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002747 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002748}
2749
2750
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002751/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002752 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002753*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002754void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002755{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002756 QCBORItem OneItemSeach[2];
2757 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2758 OneItemSeach[0].label.int64 = nLabel;
2759 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2760 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002761
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002762 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002763 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002764}
2765
2766
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002767/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002768 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002769*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002770void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002771{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002772 QCBORItem OneItemSeach[2];
2773 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2774 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2775 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2776 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002777
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002778 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002779}
2780
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002781/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002782 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002783*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002784void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002785{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002786 QCBORItem OneItemSeach[2];
2787 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2788 OneItemSeach[0].label.int64 = nLabel;
2789 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2790 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002791
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002792 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002793}
2794
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002795/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002796 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002797*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002798void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2799{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002800 QCBORItem OneItemSeach[2];
2801 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2802 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2803 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2804 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002805
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002806 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002807}
2808
2809
Laurence Lundblade02625d42020-06-25 14:41:41 -07002810// Semi-private function
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002811void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002812{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002813 QCBORError uErr;
2814
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002815 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002816 if(pMe->uLastError != QCBOR_SUCCESS) {
2817 // Already in error state; do nothing.
2818 return;
2819 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002820
2821 /* Get the data item that is the map that is being searched */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002822 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002823 uErr = QCBORDecode_GetNext(pMe, &Item);
2824 if(uErr != QCBOR_SUCCESS) {
2825 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002826 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002827 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002828 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
2829 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002830 }
2831
Laurence Lundbladef0499502020-08-01 11:55:57 -07002832 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07002833 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002834 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
2835 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002836 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002837 pMe->nesting.pCurrent->u.ma.uCountCursor++;
2838 }
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002839 // Special case to increment nesting level for zero-length maps and arrays entered in bounded mode.
2840 DecodeNesting_Descend(&(pMe->nesting), uType);
2841 }
2842
Laurence Lundblade02625d42020-06-25 14:41:41 -07002843 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002844
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002845 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
2846 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002847
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002848Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002849 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002850}
2851
Laurence Lundblade02625d42020-06-25 14:41:41 -07002852
2853/*
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002854 This is the common work for exiting a level that is a bounded map, array or bstr
2855 wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07002856
2857 One chunk of work is to set up the pre-order traversal so it is at
2858 the item just after the bounded map, array or bstr that is being
2859 exited. This is somewhat complex.
2860
2861 The other work is to level-up the bounded mode to next higest bounded
2862 mode or the top level if there isn't one.
2863 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002864static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002865ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002866{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002867 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002868
Laurence Lundblade02625d42020-06-25 14:41:41 -07002869 /*
2870 First the pre-order-traversal byte offset is positioned to the
2871 item just after the bounded mode item that was just consumed.
2872 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002873 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2874
Laurence Lundblade02625d42020-06-25 14:41:41 -07002875 /*
2876 Next, set the current nesting level to one above the bounded level
2877 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002878
Laurence Lundblade02625d42020-06-25 14:41:41 -07002879 DecodeNesting_CheckBoundedType() is always called before this and
2880 makes sure pCurrentBounded is valid.
2881 */
2882 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2883
2884 /*
2885 This does the complex work of leveling up the pre-order traversal
2886 when the end of a map or array or another bounded level is
2887 reached. It may do nothing, or ascend all the way to the top
2888 level.
2889 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07002890 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002891 if(uErr != QCBOR_SUCCESS) {
2892 goto Done;
2893 }
2894
Laurence Lundblade02625d42020-06-25 14:41:41 -07002895 /*
2896 This makes the next highest bounded level the current bounded
2897 level. If there is no next highest level, then no bounded mode is
2898 in effect.
2899 */
2900 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002901
Laurence Lundblade02625d42020-06-25 14:41:41 -07002902 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002903
2904Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002905 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002906 return uErr;
2907}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002908
Laurence Lundblade02625d42020-06-25 14:41:41 -07002909
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002910// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002911void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002912{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002913 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002914 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002915 return;
2916 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002917
Laurence Lundblade02625d42020-06-25 14:41:41 -07002918 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002919
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002920 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002921 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2922 goto Done;
2923 }
2924
Laurence Lundblade02625d42020-06-25 14:41:41 -07002925 /*
2926 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002927 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002928 from previous map search, then do a dummy search.
2929 */
2930 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002931 QCBORItem Dummy;
2932 Dummy.uLabelType = QCBOR_TYPE_NONE;
2933 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2934 if(uErr != QCBOR_SUCCESS) {
2935 goto Done;
2936 }
2937 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002938
Laurence Lundblade02625d42020-06-25 14:41:41 -07002939 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002940
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002941Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002942 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002943}
2944
2945
Laurence Lundblade1341c592020-04-11 14:19:05 -07002946
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002947static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002948 const QCBORItem *pItem,
2949 uint8_t uTagRequirement,
2950 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002951{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002952 if(pBstr) {
2953 *pBstr = NULLUsefulBufC;
2954 }
2955
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002956 if(pMe->uLastError != QCBOR_SUCCESS) {
2957 // Already in error state; do nothing.
2958 return pMe->uLastError;
2959 }
2960
2961 QCBORError uError = QCBOR_SUCCESS;
2962
2963 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2964 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2965 goto Done;;
2966 }
2967
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07002968 const TagSpecification TagSpec =
2969 {
2970 uTagRequirement,
2971 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
2972 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
2973 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002974
2975 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2976 if(uError != QCBOR_SUCCESS) {
2977 goto Done;
2978 }
2979
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002980 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002981 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002982 so the increment in NestLevelAscender called by ExitBoundedLevel()
2983 will work right. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002984 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002985 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002986
2987 if(pBstr) {
2988 *pBstr = pItem->val.string;
2989 }
2990
2991 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002992
2993 // Need to move UIB input cursor to the right place
2994
2995 // Really this is a subtraction and an assignment; not much code
2996 // There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002997 // The bstr was just consumed so the cursor is at the next item after it
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002998
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002999 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003000
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003001 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
3002
3003 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003004
Laurence Lundblade02625d42020-06-25 14:41:41 -07003005 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
3006 uPreviousLength,
3007 uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003008Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07003009 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003010
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003011 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003012}
3013
3014
Laurence Lundblade02625d42020-06-25 14:41:41 -07003015/*
3016 Public function, see header qcbor/qcbor_decode.h file
3017 */
3018void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003019 uint8_t uTagRequirement,
3020 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003021{
3022 if(pMe->uLastError != QCBOR_SUCCESS) {
3023 // Already in error state; do nothing.
3024 return;
3025 }
3026
3027 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003028 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003029 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3030 if(pMe->uLastError != QCBOR_SUCCESS) {
3031 return;
3032 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003033
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003034 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003035 &Item,
3036 uTagRequirement,
3037 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003038}
3039
3040
Laurence Lundblade02625d42020-06-25 14:41:41 -07003041/*
3042 Public function, see header qcbor/qcbor_decode.h file
3043 */
3044void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003045 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003046 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003047 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003048{
3049 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003050 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003051
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003052 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003053}
3054
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003055
Laurence Lundblade02625d42020-06-25 14:41:41 -07003056/*
3057 Public function, see header qcbor/qcbor_decode.h file
3058 */
3059void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003060 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003061 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003062 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003063{
3064 QCBORItem Item;
3065 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3066
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003067 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003068}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003069
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003070
Laurence Lundblade02625d42020-06-25 14:41:41 -07003071/*
3072 Public function, see header qcbor/qcbor_decode.h file
3073 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003074void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003075{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003076 if(pMe->uLastError != QCBOR_SUCCESS) {
3077 // Already in error state; do nothing.
3078 return;
3079 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003080
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003081 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003082 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3083 return;
3084 }
3085
3086 /*
3087 Reset the length of the UsefulInputBuf to what it was before
3088 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003089 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003090 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3091 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003092
3093
Laurence Lundblade02625d42020-06-25 14:41:41 -07003094 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003095 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003096}
3097
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003098
Laurence Lundbladee6430642020-03-14 21:15:44 -07003099
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003100
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003101
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003102
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003103
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003104
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003105static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3106{
3107 switch(pItem->uDataType) {
3108 case QCBOR_TYPE_TRUE:
3109 *pBool = true;
3110 return QCBOR_SUCCESS;
3111 break;
3112
3113 case QCBOR_TYPE_FALSE:
3114 *pBool = false;
3115 return QCBOR_SUCCESS;
3116 break;
3117
3118 default:
3119 return QCBOR_ERR_UNEXPECTED_TYPE;
3120 break;
3121 }
3122}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003123
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003124
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003125/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003126 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003127*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003128void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003129{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003130 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003131 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003132 return;
3133 }
3134
Laurence Lundbladec4537442020-04-14 18:53:22 -07003135 QCBORError nError;
3136 QCBORItem Item;
3137
3138 nError = QCBORDecode_GetNext(pMe, &Item);
3139 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003140 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003141 return;
3142 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003143 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003144}
3145
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003146
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003147/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003148 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003149*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003150void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003151{
3152 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003153 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003154
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003155 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003156}
3157
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003158
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003159/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003160 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003161*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003162void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3163{
3164 QCBORItem Item;
3165 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3166
3167 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3168}
3169
3170
3171
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003172void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3173 TagSpecification TagSpec,
3174 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003175{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003176 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003177 // Already in error state, do nothing
3178 return;
3179 }
3180
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003181 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003182 QCBORItem Item;
3183
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003184 uError = QCBORDecode_GetNext(pMe, &Item);
3185 if(uError != QCBOR_SUCCESS) {
3186 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003187 return;
3188 }
3189
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003190 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3191
3192 if(pMe->uLastError == QCBOR_SUCCESS) {
3193 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003194 }
3195}
3196
Laurence Lundbladec4537442020-04-14 18:53:22 -07003197
3198
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003199
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003200static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003201 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003202 UsefulBufC *pValue,
3203 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003204{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003205 const TagSpecification TagSpec =
3206 {
3207 uTagRequirement,
3208 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE},
3209 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3210 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003211
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003212 QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
3213 if(uErr != QCBOR_SUCCESS) {
3214 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003215 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003216
3217 *pValue = pItem->val.string;
3218
3219 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3220 *pbIsNegative = false;
3221 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3222 *pbIsNegative = true;
3223 }
3224
3225 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003226}
3227
3228
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003229/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003230 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003231 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003232void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3233 uint8_t uTagRequirement,
3234 UsefulBufC *pValue,
3235 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003236{
3237 if(pMe->uLastError != QCBOR_SUCCESS) {
3238 // Already in error state, do nothing
3239 return;
3240 }
3241
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003242 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003243 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3244 if(uError != QCBOR_SUCCESS) {
3245 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003246 return;
3247 }
3248
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003249 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003250}
3251
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003252
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003253/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003254 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003255*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003256void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3257 int64_t nLabel,
3258 uint8_t uTagRequirement,
3259 UsefulBufC *pValue,
3260 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003261{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003262 QCBORItem Item;
3263 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003264 if(pMe->uLastError != QCBOR_SUCCESS) {
3265 return;
3266 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003267
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003268 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003269}
3270
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003271
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003272/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003273 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003274*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003275void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3276 const char *szLabel,
3277 uint8_t uTagRequirement,
3278 UsefulBufC *pValue,
3279 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003280{
3281 QCBORItem Item;
3282 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003283 if(pMe->uLastError != QCBOR_SUCCESS) {
3284 return;
3285 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003286
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003287 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003288}
3289
3290
3291
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003292
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003293// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003294QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3295 const QCBORItem *pItem,
3296 UsefulBufC *pMessage,
3297 bool *pbIsNot7Bit)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003298{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003299 const TagSpecification TagSpecText =
3300 {
3301 uTagRequirement,
3302 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3303 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3304 };
3305 const TagSpecification TagSpecBinary =
3306 {
3307 uTagRequirement,
3308 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3309 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3310 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003311
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003312 QCBORError uReturn;
3313
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003314 if(CheckTagRequirement(TagSpecText, pItem->uDataType) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003315 *pMessage = pItem->val.string;
3316 if(pbIsNot7Bit != NULL) {
3317 *pbIsNot7Bit = false;
3318 }
3319 uReturn = QCBOR_SUCCESS;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003320 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003321 *pMessage = pItem->val.string;
3322 if(pbIsNot7Bit != NULL) {
3323 *pbIsNot7Bit = true;
3324 }
3325 uReturn = QCBOR_SUCCESS;
3326
3327 } else {
3328 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3329 }
3330
3331 return uReturn;
3332}
3333
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003334// Improvement: add methods for wrapped CBOR, a simple alternate to EnterBstrWrapped
3335
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003336
3337
3338
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003339#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003340
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003341typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003342
3343
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003344// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003345static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003346{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003347 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003348
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003349 if(uResult != 0) {
3350 /* This loop will run a maximum of 19 times because
3351 * UINT64_MAX < 10 ^^ 19. More than that will cause
3352 * exit with the overflow error
3353 */
3354 for(; nExponent > 0; nExponent--) {
3355 if(uResult > UINT64_MAX / 10) {
3356 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3357 }
3358 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003359 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003360
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003361 for(; nExponent < 0; nExponent++) {
3362 uResult = uResult / 10;
3363 if(uResult == 0) {
3364 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3365 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003366 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003367 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003368 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003369
3370 *puResult = uResult;
3371
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003372 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003373}
3374
3375
Laurence Lundbladee6430642020-03-14 21:15:44 -07003376/* Convert a decimal fraction to an int64_t without using
3377 floating point or math libraries. Most decimal fractions
3378 will not fit in an int64_t and this will error out with
3379 under or overflow
3380 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003381static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003382{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003383 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003384
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003385 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003386
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003387 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003388 * INT64_MAX < 2^31. More than that will cause
3389 * exist with the overflow error
3390 */
3391 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003392 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003393 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003394 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003395 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003396 nExponent--;
3397 }
3398
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003399 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003400 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003401 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3402 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003403 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003404 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003405 }
3406
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003407 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003408
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003409 return QCBOR_SUCCESS;
3410}
3411
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003412/*
3413 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3414 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003415static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3416{
3417 uint64_t uResult;
3418
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003419 // Take the absolute value of the mantissa and convert to unsigned.
3420 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003421 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3422
3423 // Do the exponentiation of the positive mantissa
3424 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3425 if(uReturn) {
3426 return uReturn;
3427 }
3428
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003429
Laurence Lundblade983500d2020-05-14 11:49:34 -07003430 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3431 of INT64_MIN. This assumes two's compliment representation where
3432 INT64_MIN is one increment farther from 0 than INT64_MAX.
3433 Trying to write -INT64_MIN doesn't work to get this because the
3434 compiler tries to work with an int64_t which can't represent
3435 -INT64_MIN.
3436 */
3437 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3438
3439 // Error out if too large
3440 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003441 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3442 }
3443
3444 // Casts are safe because of checks above
3445 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3446
3447 return QCBOR_SUCCESS;
3448}
3449
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003450/*
3451 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3452 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003453static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3454{
3455 if(nMantissa < 0) {
3456 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3457 }
3458
3459 // Cast to unsigned is OK because of check for negative
3460 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3461 // Exponentiation is straight forward
3462 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3463}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003464#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3465
3466
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003467
3468
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003469#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003470
3471
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003472static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003473{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003474 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003475
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003476 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003477 const uint8_t *pByte = BigNum.ptr;
3478 size_t uLen = BigNum.len;
3479 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003480 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003481 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003482 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003483 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003484 }
3485
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003486 *pResult = uResult;
3487 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003488}
3489
Laurence Lundblade887add82020-05-17 05:50:34 -07003490static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003491{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003492 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003493}
3494
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003495static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003496{
3497 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003498 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3499 if(uError) {
3500 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003501 }
3502 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3503 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003504 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003505}
3506
3507
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003508static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003509{
3510 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003511 /* negaative int furthest from zero is INT64_MIN
3512 which is expressed as -INT64_MAX-1. The value of
3513 a negative bignum is -n-1, one further from zero
3514 than the positive bignum */
3515
3516 /* say INT64_MIN is -2; then INT64_MAX is 1.
3517 Then -n-1 <= INT64_MIN.
3518 Then -n -1 <= -INT64_MAX - 1
3519 THen n <= INT64_MAX. */
3520 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003521 if(uError) {
3522 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003523 }
3524 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003525 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003526 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003527 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003528 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003529}
3530
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003531
3532static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
3533{
3534 while((uInt & 0xff00000000000000UL) == 0) {
3535 uInt = uInt << 8;
3536 };
3537
3538 UsefulOutBuf UOB;
3539
3540 UsefulOutBuf_Init(&UOB, Buffer);
3541
3542 while(uInt) {
3543 const uint64_t xx = uInt & 0xff00000000000000UL;
3544 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
3545 uInt = uInt << 8;
3546 (void)xx;
3547 }
3548
3549 return UsefulOutBuf_OutUBuf(&UOB);
3550}
3551
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003552#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003553
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003554
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003555/*
3556Convert a integers and floats to an int64_t.
3557
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003558\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003559
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003560\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003561
3562\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3563
3564\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3565
3566*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003567static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003568{
3569 switch(pItem->uDataType) {
3570 // TODO: float when ifdefs are set
3571 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003572 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003573 // TODO: what about under/overflow here?
3574 // Invokes the floating-point HW and/or compiler-added libraries
3575 feclearexcept(FE_ALL_EXCEPT);
3576 *pnValue = llround(pItem->val.dfnum);
3577 if(fetestexcept(FE_INVALID)) {
3578 // TODO: better error code
3579 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3580 }
3581 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003582 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003583 }
3584 break;
3585
3586 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003587 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003588 *pnValue = pItem->val.int64;
3589 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003590 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003591 }
3592 break;
3593
3594 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003595 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003596 if(pItem->val.uint64 < INT64_MAX) {
3597 *pnValue = pItem->val.int64;
3598 } else {
3599 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3600 }
3601 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003602 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003603 }
3604 break;
3605
3606 default:
3607 return QCBOR_ERR_UNEXPECTED_TYPE;
3608 }
3609 return QCBOR_SUCCESS;
3610}
3611
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003612
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003613void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003614 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003615 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003616 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003617{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003618 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003619 return;
3620 }
3621
Laurence Lundbladee6430642020-03-14 21:15:44 -07003622 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003623 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3624 if(uError) {
3625 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003626 return;
3627 }
3628
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003629 if(pItem) {
3630 *pItem = Item;
3631 }
3632
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003633 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003634}
3635
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003636
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003637void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3638 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003639 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003640 int64_t *pnValue,
3641 QCBORItem *pItem)
3642{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003643 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003644 if(pMe->uLastError != QCBOR_SUCCESS) {
3645 return;
3646 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003647
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003648 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003649}
3650
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003651
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003652void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3653 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003654 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003655 int64_t *pnValue,
3656 QCBORItem *pItem)
3657{
3658 if(pMe->uLastError != QCBOR_SUCCESS) {
3659 return;
3660 }
3661
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003662 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003663 if(pMe->uLastError != QCBOR_SUCCESS) {
3664 return;
3665 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003666
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003667 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003668}
3669
3670
3671
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003672/*
3673 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003674
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003675 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003676
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003677 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003678
3679 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3680
3681 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3682
3683 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003684static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003685{
3686 QCBORError uErr;
3687
3688 switch(pItem->uDataType) {
3689
3690 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003691 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003692 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003693 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003694 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003695 }
3696 break;
3697
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003698 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003699 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003700 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003701 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003702 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003703 }
3704 break;
3705
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003706#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3707 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003708 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003709 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3710 pItem->val.expAndMantissa.nExponent,
3711 pnValue,
3712 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003713 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003714 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003715 }
3716 break;
3717
3718 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003719 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003720 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3721 pItem->val.expAndMantissa.nExponent,
3722 pnValue,
3723 Exponentitate2);
3724 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003725 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003726 }
3727 break;
3728
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003729 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003730 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003731 int64_t nMantissa;
3732 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3733 if(uErr) {
3734 return uErr;
3735 }
3736 return ExponentiateNN(nMantissa,
3737 pItem->val.expAndMantissa.nExponent,
3738 pnValue,
3739 Exponentitate10);
3740 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003741 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003742 }
3743 break;
3744
3745 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003746 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003747 int64_t nMantissa;
3748 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3749 if(uErr) {
3750 return uErr;
3751 }
3752 return ExponentiateNN(nMantissa,
3753 pItem->val.expAndMantissa.nExponent,
3754 pnValue,
3755 Exponentitate10);
3756 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003757 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003758 }
3759 break;
3760
3761 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003762 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003763 int64_t nMantissa;
3764 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3765 if(uErr) {
3766 return uErr;
3767 }
3768 return ExponentiateNN(nMantissa,
3769 pItem->val.expAndMantissa.nExponent,
3770 pnValue,
3771 Exponentitate2);
3772 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003773 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003774 }
3775 break;
3776
3777 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003778 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003779 int64_t nMantissa;
3780 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3781 if(uErr) {
3782 return uErr;
3783 }
3784 return ExponentiateNN(nMantissa,
3785 pItem->val.expAndMantissa.nExponent,
3786 pnValue,
3787 Exponentitate2);
3788 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003789 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003790 }
3791 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003792#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3793
Laurence Lundbladee6430642020-03-14 21:15:44 -07003794
Laurence Lundbladec4537442020-04-14 18:53:22 -07003795 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003796 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003797}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003798
3799
Laurence Lundbladec4537442020-04-14 18:53:22 -07003800/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003801 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003802 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003803void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003804{
3805 QCBORItem Item;
3806
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003807 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003808
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003809 if(pMe->uLastError == QCBOR_SUCCESS) {
3810 // The above conversion succeeded
3811 return;
3812 }
3813
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003814 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003815 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003816 return;
3817 }
3818
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003819 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003820}
3821
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003822
3823/*
3824Public function, see header qcbor/qcbor_decode.h file
3825*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003826void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003827{
3828 QCBORItem Item;
3829
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003830 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003831
3832 if(pMe->uLastError == QCBOR_SUCCESS) {
3833 // The above conversion succeeded
3834 return;
3835 }
3836
3837 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3838 // The above conversion failed in a way that code below can't correct
3839 return;
3840 }
3841
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003842 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003843}
3844
3845
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003846/*
3847Public function, see header qcbor/qcbor_decode.h file
3848*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003849void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003850{
3851 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003852 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pnValue, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003853
3854 if(pMe->uLastError == QCBOR_SUCCESS) {
3855 // The above conversion succeeded
3856 return;
3857 }
3858
3859 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3860 // The above conversion failed in a way that code below can't correct
3861 return;
3862 }
3863
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003864 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003865}
3866
3867
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003868static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003869{
3870 switch(pItem->uDataType) {
3871 // TODO: type flaot
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07003872 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003873 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003874 feclearexcept(FE_ALL_EXCEPT);
3875 double dRounded = round(pItem->val.dfnum);
3876 // TODO: over/underflow
3877 if(fetestexcept(FE_INVALID)) {
3878 // TODO: better error code
3879 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3880 } else if(isnan(dRounded)) {
3881 // TODO: better error code
3882 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3883 } else if(dRounded >= 0) {
3884 *puValue = (uint64_t)dRounded;
3885 } else {
3886 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3887 }
3888 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003889 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003890 }
3891 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003892
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003893 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003894 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003895 if(pItem->val.int64 >= 0) {
3896 *puValue = (uint64_t)pItem->val.int64;
3897 } else {
3898 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3899 }
3900 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003901 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003902 }
3903 break;
3904
3905 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003906 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003907 *puValue = pItem->val.uint64;
3908 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003909 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003910 }
3911 break;
3912
3913 default:
3914 return QCBOR_ERR_UNEXPECTED_TYPE;
3915 }
3916 return QCBOR_SUCCESS;
3917}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003918
3919
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003920void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003921 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003922 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003923 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003924{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003925 if(pMe->uLastError != QCBOR_SUCCESS) {
3926 return;
3927 }
3928
Laurence Lundbladec4537442020-04-14 18:53:22 -07003929 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003930
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003931 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3932 if(uError) {
3933 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003934 return;
3935 }
3936
Laurence Lundbladea826c502020-05-10 21:07:00 -07003937 if(pItem) {
3938 *pItem = Item;
3939 }
3940
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003941 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003942}
3943
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003944
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003945void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int8_t *pnValue, QCBORItem *pItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003946{
3947 int64_t uValue;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003948 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, &uValue, pItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003949 if(pMe->uLastError != QCBOR_SUCCESS) {
3950 return;
3951 }
3952
3953 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3954 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3955 }
3956}
3957
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003958void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, int8_t *pnValue, QCBORItem *pItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003959{
3960 int64_t uValue;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003961 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, &uValue, pItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003962 if(pMe->uLastError != QCBOR_SUCCESS) {
3963 return;
3964 }
3965
3966 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3967 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3968 }
3969}
3970
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003971void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, int8_t *pnValue, QCBORItem *pItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003972{
3973 int64_t uValue;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003974 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, &uValue, pItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003975 if(pMe->uLastError != QCBOR_SUCCESS) {
3976 return;
3977 }
3978
3979 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3980 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3981 }
3982}
3983
3984
3985
3986
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003987void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3988 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003989 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003990 uint64_t *puValue,
3991 QCBORItem *pItem)
3992{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003993 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003994 if(pMe->uLastError != QCBOR_SUCCESS) {
3995 return;
3996 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003997
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003998 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003999}
4000
4001
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004002void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004003 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004004 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004005 uint64_t *puValue,
4006 QCBORItem *pItem)
4007{
4008 if(pMe->uLastError != QCBOR_SUCCESS) {
4009 return;
4010 }
4011
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004012 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004013 if(pMe->uLastError != QCBOR_SUCCESS) {
4014 return;
4015 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004016
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004017 pMe->uLastError = (uint8_t)ConvertUint64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004018}
4019
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004020/*
4021 Public function, see header qcbor/qcbor_decode.h file
4022*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004023static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004024{
4025 QCBORError uErr;
4026
4027 switch(pItem->uDataType) {
4028
4029 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004030 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004031 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4032 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004033 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004034 }
4035 break;
4036
4037 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004038 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004039 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4040 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004041 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004042 }
4043 break;
4044
4045#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4046
4047 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004048 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004049 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4050 pItem->val.expAndMantissa.nExponent,
4051 puValue,
4052 Exponentitate10);
4053 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004054 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004055 }
4056 break;
4057
4058 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004059 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004060 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4061 pItem->val.expAndMantissa.nExponent,
4062 puValue,
4063 Exponentitate2);
4064 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004065 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004066 }
4067 break;
4068
4069 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004070 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004071 // TODO: Would be better to convert to unsigned
4072 int64_t nMantissa;
4073 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4074 if(uErr != QCBOR_SUCCESS) {
4075 return uErr;
4076 }
4077 return ExponentitateNU(nMantissa,
4078 pItem->val.expAndMantissa.nExponent,
4079 puValue,
4080 Exponentitate10);
4081 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004082 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004083 }
4084 break;
4085
4086 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004087 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004088 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4089 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004090 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004091 }
4092 break;
4093
4094 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004095 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004096 // TODO: Would be better to convert to unsigned
4097 int64_t nMantissa;
4098 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4099 if(uErr != QCBOR_SUCCESS) {
4100 return uErr;
4101 }
4102 return ExponentitateNU(nMantissa,
4103 pItem->val.expAndMantissa.nExponent,
4104 puValue,
4105 Exponentitate2);
4106 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004107 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004108 }
4109 break;
4110
4111 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004112 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004113 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4114 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004115 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004116 }
4117 break;
4118#endif
4119 default:
4120 return QCBOR_ERR_UNEXPECTED_TYPE;
4121 }
4122}
4123
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004124/*
4125 Public function, see header qcbor/qcbor_decode.h file
4126*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004127void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004128{
4129 QCBORItem Item;
4130
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004131 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004132
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004133 if(pMe->uLastError == QCBOR_SUCCESS) {
4134 // The above conversion succeeded
4135 return;
4136 }
4137
4138 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4139 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004140 return;
4141 }
4142
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004143 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004144}
4145
Laurence Lundbladec4537442020-04-14 18:53:22 -07004146
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004147/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004148 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004149*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004150void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004151{
4152 QCBORItem Item;
4153
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004154 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004155
4156 if(pMe->uLastError == QCBOR_SUCCESS) {
4157 // The above conversion succeeded
4158 return;
4159 }
4160
4161 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4162 // The above conversion failed in a way that code below can't correct
4163 return;
4164 }
4165
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004166 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004167}
4168
4169
4170/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004171 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004172*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004173void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004174{
4175 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004176 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, puValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004177
4178 if(pMe->uLastError == QCBOR_SUCCESS) {
4179 // The above conversion succeeded
4180 return;
4181 }
4182
4183 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4184 // The above conversion failed in a way that code below can't correct
4185 return;
4186 }
4187
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004188 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004189}
4190
4191
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004192static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004193{
4194 switch(pItem->uDataType) {
4195 // TODO: float when ifdefs are set
4196 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004197 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4198 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004199 *pdValue = pItem->val.dfnum;
4200 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004201 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004202 }
4203 }
4204 break;
4205
4206 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004207 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004208 // TODO: how does this work?
4209 *pdValue = (double)pItem->val.int64;
4210
4211 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004212 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004213 }
4214 break;
4215
4216 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004217 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004218 *pdValue = (double)pItem->val.uint64;
4219 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004220 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004221 }
4222 break;
4223
4224 default:
4225 return QCBOR_ERR_UNEXPECTED_TYPE;
4226 }
4227
4228 return QCBOR_SUCCESS;
4229}
4230
4231
4232
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004233void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004234 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004235 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004236 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004237{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004238 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004239 return;
4240 }
4241
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004242 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004243
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004244 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004245 if(uError) {
4246 pMe->uLastError = (uint8_t)uError;
4247 return;
4248 }
4249
4250 if(pItem) {
4251 *pItem = Item;
4252 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004253
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004254 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004255}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004256
Laurence Lundbladec4537442020-04-14 18:53:22 -07004257
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004258void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4259 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004260 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004261 double *pdValue,
4262 QCBORItem *pItem)
4263{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004264 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004265 if(pMe->uLastError != QCBOR_SUCCESS) {
4266 return;
4267 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004268
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004269 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004270}
4271
4272void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4273 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004274 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004275 double *pdValue,
4276 QCBORItem *pItem)
4277{
4278 if(pMe->uLastError != QCBOR_SUCCESS) {
4279 return;
4280 }
4281
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004282 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004283 if(pMe->uLastError != QCBOR_SUCCESS) {
4284 return;
4285 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004286
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004287 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004288}
4289
4290
4291
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004292static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4293{
4294 double dResult;
4295
4296 dResult = 0.0;
4297 const uint8_t *pByte = BigNum.ptr;
4298 size_t uLen = BigNum.len;
4299 /* This will overflow and become the float value INFINITY if the number
4300 is too large to fit. No error will be logged.
4301 TODO: should an error be logged? */
4302 while(uLen--) {
4303 dResult = (dResult * 256.0) + (double)*pByte++;
4304 }
4305
4306 return dResult;
4307}
4308
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004309static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004310{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004311 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004312 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4313
4314 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004315 switch(pItem->uDataType) {
4316 // TODO: type float
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004317
4318#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004319 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004320 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004321 // TODO: rounding and overflow errors
4322 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4323 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4324 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004325 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004326 }
4327 break;
4328
4329 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004330 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004331 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4332 exp2((double)pItem->val.expAndMantissa.nExponent);
4333 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004334 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004335 }
4336 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004337#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004338
4339 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004340 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004341 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4342 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004343 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004344 }
4345 break;
4346
4347 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004348 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004349 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004350 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004351 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004352 }
4353 break;
4354
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004355#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004356 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004357 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004358 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4359 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4360 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004361 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004362 }
4363 break;
4364
4365 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004366 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004367 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4368 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4369 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004370 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004371 }
4372 break;
4373
4374 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004375 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004376 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4377 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4378 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004379 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004380 }
4381 break;
4382
4383 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004384 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004385 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004386 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4387 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004388 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004389 }
4390 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004391#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4392
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004393
4394 default:
4395 return QCBOR_ERR_UNEXPECTED_TYPE;
4396 }
4397
4398 return QCBOR_SUCCESS;
4399}
4400
4401
4402/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004403 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004404*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004405void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004406{
4407
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004408 QCBORItem Item;
4409
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004410 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004411
4412 if(pMe->uLastError == QCBOR_SUCCESS) {
4413 // The above conversion succeeded
4414 return;
4415 }
4416
4417 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4418 // The above conversion failed in a way that code below can't correct
4419 return;
4420 }
4421
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004422 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004423}
4424
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004425
4426/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004427 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004428*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004429void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004430{
4431 QCBORItem Item;
4432
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004433 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004434
4435 if(pMe->uLastError == QCBOR_SUCCESS) {
4436 // The above conversion succeeded
4437 return;
4438 }
4439
4440 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4441 // The above conversion failed in a way that code below can't correct
4442 return;
4443 }
4444
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004445 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004446}
4447
4448
4449/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004450 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004451*/
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004452void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004453{
4454 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004455 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004456
4457 if(pMe->uLastError == QCBOR_SUCCESS) {
4458 // The above conversion succeeded
4459 return;
4460 }
4461
4462 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4463 // The above conversion failed in a way that code below can't correct
4464 return;
4465 }
4466
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004467 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004468}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004469
4470
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004471
4472
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004473#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004474static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4475 TagSpecification TagSpec,
4476 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004477{
4478 QCBORError uErr;
4479 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004480 while(1) {
4481 uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
4482 if(uErr != QCBOR_SUCCESS) {
4483 goto Done;
4484 }
4485
4486 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4487 break; // Successful exit. Moving on to finish decoding.
4488 }
4489
4490 // The item is an array, which means an undecoded
4491 // mantissa and exponent, so decode it. It will then
4492 // have a different type and exit the loop if.
4493 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4494 if(uErr != QCBOR_SUCCESS) {
4495 goto Done;
4496 }
4497
4498 // Second time around, the type must match.
4499 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_MATCH_TAG;
4500 }
4501Done:
4502 return uErr;
4503}
4504
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004505
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004506static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004507 TagSpecification TagSpec,
4508 QCBORItem *pItem,
4509 int64_t *pnMantissa,
4510 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004511{
4512 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004513
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004514 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004515 if(uErr != QCBOR_SUCCESS) {
4516 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004517 }
4518
4519 switch (pItem->uDataType) {
4520
4521 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004522 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004523 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4524 *pnExponent = pItem->val.expAndMantissa.nExponent;
4525 break;
4526
4527 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004528 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004529 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004530 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004531 break;
4532
4533 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004534 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004535 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004536 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004537 break;
4538
4539 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004540 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004541 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004542
4543 Done:
4544 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004545}
4546
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004547
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004548static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004549 TagSpecification TagSpec,
4550 QCBORItem *pItem,
4551 UsefulBuf BufferForMantissa,
4552 UsefulBufC *pMantissa,
4553 bool *pbIsNegative,
4554 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004555{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004556 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004557
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004558 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004559 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004560 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004561 }
4562
4563 uint64_t uMantissa;
4564
4565 switch (pItem->uDataType) {
4566
4567 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004568 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004569 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
4570 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
4571 *pbIsNegative = false;
4572 } else {
4573 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
4574 *pbIsNegative = true;
4575 }
4576 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
4577 *pnExponent = pItem->val.expAndMantissa.nExponent;
4578 break;
4579
4580 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004581 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004582 *pnExponent = pItem->val.expAndMantissa.nExponent;
4583 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4584 *pbIsNegative = false;
4585 break;
4586
4587 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004588 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004589 *pnExponent = pItem->val.expAndMantissa.nExponent;
4590 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
4591 *pbIsNegative = true;
4592 break;
4593
4594 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004595 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004596 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004597
4598Done:
4599 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004600}
4601
4602
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004603/*
4604 Public function, see header qcbor/qcbor_decode.h file
4605*/
4606void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
4607 uint8_t uTagRequirement,
4608 int64_t *pnMantissa,
4609 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004610{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004611 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
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004622 const TagSpecification TagSpec =
4623 {
4624 uTagRequirement,
4625 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4626 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4627 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004628
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004629 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004630}
4631
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004632
4633/*
4634 Public function, see header qcbor/qcbor_decode.h file
4635*/
4636void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004637 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004638 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004639 int64_t *pnMantissa,
4640 int64_t *pnExponent)
4641{
4642 if(pMe->uLastError != QCBOR_SUCCESS) {
4643 return;
4644 }
4645
4646 QCBORItem Item;
4647 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4648
4649 const TagSpecification TagSpec =
4650 {
4651 uTagRequirement,
4652 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4653 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4654 };
4655
4656 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4657}
4658
4659
4660/*
4661 Public function, see header qcbor/qcbor_decode.h file
4662*/
4663void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004664 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004665 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004666 int64_t *pnMantissa,
4667 int64_t *pnExponent)
4668{
4669 if(pMe->uLastError != QCBOR_SUCCESS) {
4670 return;
4671 }
4672
4673 QCBORItem Item;
4674 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4675
4676 const TagSpecification TagSpec =
4677 {
4678 uTagRequirement,
4679 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4680 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4681 };
4682
4683 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4684}
4685
4686
4687/*
4688 Public function, see header qcbor/qcbor_decode.h file
4689*/
4690void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
4691 uint8_t uTagRequirement,
4692 UsefulBuf MantissaBuffer,
4693 UsefulBufC *pMantissa,
4694 bool *pbMantissaIsNegative,
4695 int64_t *pnExponent)
4696{
4697 if(pMe->uLastError != QCBOR_SUCCESS) {
4698 return;
4699 }
4700
4701 QCBORItem Item;
4702 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4703 if(uError) {
4704 pMe->uLastError = (uint8_t)uError;
4705 return;
4706 }
4707
4708 const TagSpecification TagSpec =
4709 {
4710 uTagRequirement,
4711 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4712 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4713 };
4714
4715 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
4716}
4717
4718
4719/*
4720 Public function, see header qcbor/qcbor_decode.h file
4721*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004722void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004723 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004724 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004725 UsefulBuf BufferForMantissa,
4726 UsefulBufC *pMantissa,
4727 bool *pbIsNegative,
4728 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004729{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004730 if(pMe->uLastError != QCBOR_SUCCESS) {
4731 return;
4732 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004733
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004734 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004735 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004736 if(pMe->uLastError != QCBOR_SUCCESS) {
4737 return;
4738 }
4739
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004740 const TagSpecification TagSpec =
4741 {
4742 uTagRequirement,
4743 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4744 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4745 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004746
4747 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004748}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004749
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004750
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004751/*
4752 Public function, see header qcbor/qcbor_decode.h file
4753*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004754void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004755 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004756 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004757 UsefulBuf BufferForMantissa,
4758 UsefulBufC *pMantissa,
4759 bool *pbIsNegative,
4760 int64_t *pnExponent)
4761{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004762 if(pMe->uLastError != QCBOR_SUCCESS) {
4763 return;
4764 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004765
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004766 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004767 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4768 if(pMe->uLastError != QCBOR_SUCCESS) {
4769 return;
4770 }
4771
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004772 const TagSpecification TagSpec =
4773 {
4774 uTagRequirement,
4775 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
4776 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4777 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004778
4779 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
4780}
4781
4782
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004783/*
4784 Public function, see header qcbor/qcbor_decode.h file
4785*/
4786void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
4787 uint8_t uTagRequirement,
4788 int64_t *pnMantissa,
4789 int64_t *pnExponent)
4790{
4791 if(pMe->uLastError != QCBOR_SUCCESS) {
4792 return;
4793 }
4794
4795 QCBORItem Item;
4796 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4797 if(uError) {
4798 pMe->uLastError = (uint8_t)uError;
4799 return;
4800 }
4801 const TagSpecification TagSpec =
4802 {
4803 uTagRequirement,
4804 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4805 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4806 };
4807
4808 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4809}
4810
4811
4812/*
4813 Public function, see header qcbor/qcbor_decode.h file
4814*/
4815void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004816 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004817 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004818 int64_t *pnMantissa,
4819 int64_t *pnExponent)
4820{
4821 if(pMe->uLastError != QCBOR_SUCCESS) {
4822 return;
4823 }
4824
4825 QCBORItem Item;
4826 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4827 if(pMe->uLastError != QCBOR_SUCCESS) {
4828 return;
4829 }
4830
4831 const TagSpecification TagSpec =
4832 {
4833 uTagRequirement,
4834 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4835 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4836 };
4837
4838 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4839}
4840
4841
4842/*
4843 Public function, see header qcbor/qcbor_decode.h file
4844*/
4845void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004846 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004847 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004848 int64_t *pnMantissa,
4849 int64_t *pnExponent)
4850{
4851 if(pMe->uLastError != QCBOR_SUCCESS) {
4852 return;
4853 }
4854
4855 QCBORItem Item;
4856 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4857 if(pMe->uLastError != QCBOR_SUCCESS) {
4858 return;
4859 }
4860
4861 const TagSpecification TagSpec =
4862 {
4863 uTagRequirement,
4864 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4865 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4866 };
4867
4868 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
4869}
4870
4871
4872/*
4873 Public function, see header qcbor/qcbor_decode.h file
4874*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004875void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
4876 uint8_t uTagRequirement,
4877 UsefulBuf MantissaBuffer,
4878 UsefulBufC *pMantissa,
4879 bool *pbMantissaIsNegative,
4880 int64_t *pnExponent)
4881{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004882 if(pMe->uLastError != QCBOR_SUCCESS) {
4883 return;
4884 }
4885
4886 QCBORItem Item;
4887 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4888 if(uError) {
4889 pMe->uLastError = (uint8_t)uError;
4890 return;
4891 }
4892
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004893 const TagSpecification TagSpec =
4894 {
4895 uTagRequirement,
4896 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4897 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4898 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004899
4900 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004901}
4902
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004903
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004904/*
4905 Public function, see header qcbor/qcbor_decode.h file
4906*/
4907void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004908 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004909 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004910 UsefulBuf BufferForMantissa,
4911 UsefulBufC *pMantissa,
4912 bool *pbIsNegative,
4913 int64_t *pnExponent)
4914{
4915 if(pMe->uLastError != QCBOR_SUCCESS) {
4916 return;
4917 }
4918
4919 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004920 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4921 if(pMe->uLastError != QCBOR_SUCCESS) {
4922 return;
4923 }
4924
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004925 const TagSpecification TagSpec =
4926 {
4927 uTagRequirement,
4928 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4929 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4930 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004931
4932 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
4933}
4934
4935
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004936/*
4937 Public function, see header qcbor/qcbor_decode.h file
4938*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004939void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004940 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004941 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004942 UsefulBuf BufferForMantissa,
4943 UsefulBufC *pMantissa,
4944 bool *pbIsNegative,
4945 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004946{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004947 if(pMe->uLastError != QCBOR_SUCCESS) {
4948 return;
4949 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004950
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004951 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004952 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4953 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004954 return;
4955 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004956
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004957 const TagSpecification TagSpec =
4958 {
4959 uTagRequirement,
4960 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
4961 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4962 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004963
4964 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004965}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004966
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004967#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */