blob: 810a814d699a53c9105b83b4fd7ac6f5e21c99d9 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070035#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070036
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070037
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053038/*
39 This casts away the const-ness of a pointer, usually so it can be
40 freed or realloced.
41 */
42#define UNCONST_POINTER(ptr) ((void *)(ptr))
43
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070044
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070045
Laurence Lundblade02625d42020-06-25 14:41:41 -070046inline static bool
47// TODO: add more tests for QCBOR_TYPE_MAP_AS_ARRAY mode in qcbor_decode_tests.c
48QCBORItem_IsMapOrArray(const QCBORItem *pMe)
49{
50 const uint8_t uDataType = pMe->uDataType;
51 return uDataType == QCBOR_TYPE_MAP ||
52 uDataType == QCBOR_TYPE_ARRAY ||
53 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
54}
55
56inline static bool
57QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
58{
59 if(!QCBORItem_IsMapOrArray(pMe)){
60 return false;
61 }
62
63 if(pMe->val.uCount != 0) {
64 return false;
65 }
66 return true;
67}
68
69inline static bool
70QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
71{
72 if(!QCBORItem_IsMapOrArray(pMe)){
73 return false;
74 }
75
76 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
77 return false;
78 }
79 return true;
80}
81
82
Laurence Lundbladeee851742020-01-08 08:37:05 -080083/*===========================================================================
Laurence Lundblade02625d42020-06-25 14:41:41 -070084 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080085
Laurence Lundblade02625d42020-06-25 14:41:41 -070086 See qcbor/qcbor_private.h for definition of the object
87 described here: QCBORDecodeNesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080088 ===========================================================================*/
89
Laurence Lundblade9c905e82020-04-25 11:31:38 -070090/*
91The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...)
92formed by intermediate nodes (arrays and maps). The cursor for the traversal
93 is the byte offset in the encoded input and a leaf counter for definite
94 length maps and arrays. Indefinite length maps and arrays are handled
95 by look ahead for the break.
96
97 The view presented to the caller has tags, labels and the chunks of
98 indefinite length strings aggregated into one decorated data item.
99
100The caller understands the nesting level in pre-order traversal by
101 the fact that a data item that is a map or array is presented to
102 the caller when it is first encountered in the pre-order traversal and that all data items are presented with its nesting level
103 and the nesting level of the next item.
104
105 The caller traverse maps and arrays in a special mode that often more convenient
106 that tracking by nesting level. When an array or map is expected or encountered
107 the EnterMap or EnteryArray can be called.
108
109 When entering a map or array like this, the cursor points to the first
110 item in the map or array. When exiting, it points to the item after
111 the map or array, regardless of whether the items in the map or array were
112 all traversed.
113
114 When in a map or array, the cursor functions as normal, but traversal
115 cannot go past the end of the map or array that was entered. If this
116 is attempted the QCBOR_ERR_NO_MORE_ITEMS error is returned. To
117 go past the end of the map or array ExitMap() or ExitArray() must
118 be called. It can be called any time regardless of the position
119 of the cursor.
120
121 When a map is entered, a special function allows fetching data items
122 by label. This call will traversal the whole map looking for the
123 labeled item. The whole map is traversed so as to detect duplicates.
124 This type of fetching items does not affect the normal traversal
125 cursor.
126
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700127
128When a data item is presented to the caller, the nesting level of the data
129 item is presented along with the nesting level of the item that would be
130 next consumed.
131
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700132 */
133
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700134
135inline static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700136DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700137{
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700138 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700139 /*
140 Limit in DecodeNesting_Descend against more than
141 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
142 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700143 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700144}
145
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700146
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700147inline static uint8_t
148DecodeNesting_GetBoundedModeLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700149{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700150 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pMapsAndArrays[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700151 /*
152 Limit in DecodeNesting_Descend against more than
153 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
154 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700155 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700156}
157
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700158
Laurence Lundblade02625d42020-06-25 14:41:41 -0700159static inline size_t
160DecodeNesting_GetMapOrArrayStart(QCBORDecodeNesting *pNesting)
161{
162 return pNesting->pCurrentBounded->u.ma.uStartOffset;
163}
164
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700165
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700166inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700167DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700168{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700169 if(pNesting->pCurrent == &(pNesting->pMapsAndArrays[0])) {
170 return true;
171 } else {
172 return false;
173 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700174}
175
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700176
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700177inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700178DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700179{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700180 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
181 /* Not a map or array */
182 return false;
183 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700184 if(pNesting->pCurrent->u.ma.uCountTotal != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700185 /* Not indefinte length */
186 return false;
187 }
188 /* All checks passed; is an indefinte length map or array */
189 return true;
190}
191
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700192
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700193inline static bool
194DecodeNesting_IsDefiniteLength(const QCBORDecodeNesting *pNesting)
195{
196 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
197 /* Not a map or array */
198 return false;
199 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700200 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700201 /* Is indefinite */
202 return false;
203 }
204 /* All checks passed; is a definte length map or array */
205 return true;
206}
207
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700208
Laurence Lundblade642282a2020-06-23 12:00:33 -0700209inline static bool
210DecodeNesting_IsBstrWrapped(const QCBORDecodeNesting *pNesting)
211{
212 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
213 /* is a byte string */
214 return true;
215 }
216 return false;
217}
218
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700219
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700220inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700221{
222 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
223 return true;
224 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700225 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700226 return true;
227 }
228 return false;
229}
230
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700231
Laurence Lundblade02625d42020-06-25 14:41:41 -0700232inline static void DecodeNesting_SetMapOrArrayBoundedMode(const QCBORDecodeNesting *pNesting, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700233{
234 // Should be only called on maps and arrays
235 // TODO: check this cast, maybe give an error?
236 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
237}
238
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700239
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700240inline static void DecodeNesting_ClearBoundedMode(const QCBORDecodeNesting *pNesting)
241{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700242 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700243}
244
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700245
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700246inline static bool
Laurence Lundblade642282a2020-06-23 12:00:33 -0700247DecodeNesting_IsAtEndOfBoundedDefiniteLenMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700248{
249 if(pNesting->pCurrentBounded == NULL) {
250 /* No bounded map or array or... set up. */
251 return false;
252 }
253 if(pNesting->pCurrentBounded->uLevelType == QCBOR_TYPE_BYTE_STRING) {
254 /* Not a map or array */
255 return false;
256 }
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700257 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700258 /* Not in bounded mode. */
259 return false;
260 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700261 if(pNesting->pCurrentBounded->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700262 /* An indefinite length map or array */
263 return false;
264 }
265 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
266 /* Count is not zero, still unconsumed items. */
267 return false;
268 }
269 /* All checks passed, got to the end of a definite length map or array */
270 return true;
271}
272
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700273inline static bool
274DecodeNesting_IsAtEndOfBoundedFarf(const QCBORDecodeNesting *pNesting)
275{
276 if(pNesting->pCurrentBounded == NULL) {
277 /* No bounded map or array or... set up. */
278 return false;
279 }
280 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
281 /* Not a map or array */
282 return false;
283 }
284 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
285 /* Not in bounded mode. */
286 return false;
287 }
288#if 0
289 if(pNesting->pCurrentBounded->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
290 /* An indefinite length map or array */
291 return false;
292 }
293 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
294 /* Count is not zero, still unconsumed items. */
295 return false;
296 }
297#endif
298 /* All checks passed, got to the end of a definite length map or array */
299 return true;
300}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700301
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700302inline static bool
303DecodeNesting_IsEndOfDefiniteLengthMapOrArray(QCBORDecodeNesting *pNesting)
304{
305 /* Must only be called on map / array; TODO: add checks? */
306 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
307 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700308 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700309 return false;
310 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700311}
312
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700313
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700314inline static bool
315DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700316{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700317 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
318 return true;
319 } else {
320 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700321 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700322}
323
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700324
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700325inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700326DecodeNesting_CheckBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700327{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700328 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700329 return false;
330 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700331
332 if(pNesting->pCurrentBounded->uLevelType != uType) {
333 return false;
334 }
335
336 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700337}
338
Laurence Lundblade02625d42020-06-25 14:41:41 -0700339
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700340inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700341DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700342{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700343 /* Only call on array / map; TODO: add check?*/
344 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700345}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700346
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700347
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700348inline static void
349DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
350{
351 pNesting->pCurrent--;
352}
353
Laurence Lundblade02625d42020-06-25 14:41:41 -0700354
355static QCBORError
356DecodeNesting_Decsend(QCBORDecodeNesting *pNesting, uint8_t uType)
357{
358 // Error out if nesting is too deep
359 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
360 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
361 }
362
363 // The actual descend
364 pNesting->pCurrent++;
365
366 pNesting->pCurrent->uLevelType = uType;
367
368 return QCBOR_SUCCESS;
369}
370
371
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700372inline static void
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700373DecodeNesting_EnterBoundedMode(QCBORDecodeNesting *pNesting, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700374{
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700375 /* Have descended into this before this is called. The job here is just to mark it in bounded mode */
376 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700377 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, uOffset);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700378}
379
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700380
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700381inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700382DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700383 uint8_t uQCBORType,
384 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700385{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700386 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700387
388 if(uCount == 0) {
389 // Nothing to do for empty definite lenth arrays. They are just are
390 // effectively the same as an item that is not a map or array
391 goto Done;
392 // Empty indefinite length maps and arrays are handled elsewhere
393 }
394
395 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700396 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
397 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
398 uError = QCBOR_ERR_ARRAY_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700399 goto Done;
400 }
401
Laurence Lundblade02625d42020-06-25 14:41:41 -0700402 uError = DecodeNesting_Decsend(pNesting, uQCBORType);
403 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700404 goto Done;
405 }
406
Laurence Lundblade02625d42020-06-25 14:41:41 -0700407 // Fill in the new map/array level. Check above makes cast OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700408 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
409 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700410
411 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700412
413Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700414 return uError;;
415}
416
417
418static inline void
419DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
420{
421 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
422}
423
424
425static inline void
426DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
427{
428 while(pNesting->pCurrentBounded != &(pNesting->pMapsAndArrays[0])) {
429 pNesting->pCurrentBounded--;
430 if(DecodeNesting_IsCurrentBounded(pNesting)) {
431 break;
432 }
433 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700434}
435
436
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700437inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700438DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
439 size_t uEndOffset,
440 size_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700441{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700442 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700443
Laurence Lundblade02625d42020-06-25 14:41:41 -0700444 uError = DecodeNesting_Decsend(pNesting, QCBOR_TYPE_BYTE_STRING);
445 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700446 goto Done;
447 }
448
Laurence Lundblade02625d42020-06-25 14:41:41 -0700449 // Fill in the new byte string level
450 // TODO: justify cast
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700451 pNesting->pCurrent->u.bs.uPreviousEndOffset = (uint32_t)uEndOffset;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700452 pNesting->pCurrent->u.bs.uEndOfBstr = (uint32_t)uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700453
Laurence Lundblade02625d42020-06-25 14:41:41 -0700454 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700455 pNesting->pCurrentBounded = pNesting->pCurrent;
456
457Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700458 return uError;;
459}
460
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700461#include <stdlib.h>
462// TODO: use or get rid of
463void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700464DecodeNesting_ZeroDefiniteLengthCount(QCBORDecodeNesting *pNesting)
465{
466 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700467}
468
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700469
Laurence Lundbladeee851742020-01-08 08:37:05 -0800470inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700471DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700472{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700473 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700474 pNesting->pMapsAndArrays[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700475 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
476}
477
478
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700479inline static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700480DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700481{
482 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700483 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700484
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700485 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700486 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700487 }
488}
489
Laurence Lundblade02625d42020-06-25 14:41:41 -0700490static inline void
491DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700492{
493 *pNesting = *pSave;
494}
495
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700496
Laurence Lundblade02625d42020-06-25 14:41:41 -0700497static inline uint32_t
498DecodeNesting_GetEndOfBstr(QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700499{
500 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
501}
502
503
Laurence Lundblade02625d42020-06-25 14:41:41 -0700504static inline uint32_t
505DecodeNesting_GetPreviousBoundedEnd(QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700506{
507 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
508}
509
510
Laurence Lundblade02625d42020-06-25 14:41:41 -0700511#include <stdio.h>
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700512
513const char *TypeStr(uint8_t type)
514{
515 switch(type) {
516 case QCBOR_TYPE_MAP: return " map";
517 case QCBOR_TYPE_ARRAY: return "array";
518 case QCBOR_TYPE_BYTE_STRING: return " bstr";
519 default: return " --- ";
520 }
521}
522
523static char buf[20]; // Not thread safe, but that is OK
524const char *CountString(uint16_t uCount, uint16_t uTotal)
525{
526 if(uTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
527 strcpy(buf, "indefinite");
528 } else {
529 sprintf(buf, "%d/%d", uCount, uTotal);
530 }
531 return buf;
532}
533
Laurence Lundblade02625d42020-06-25 14:41:41 -0700534void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700535{
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700536 printf("---%s--%d/%d--\narrow is current bounded level\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700537 szName,
538 (uint32_t)pBuf->cursor,
539 (uint32_t)pBuf->UB.len);
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700540
541 printf("Level Type Count Offsets \n");
Laurence Lundblade02625d42020-06-25 14:41:41 -0700542 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
543 if(&(pNesting->pMapsAndArrays[i]) > pNesting->pCurrent) {
544 break;
545 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700546
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700547 printf("%2s %2d %s ",
548 pNesting->pCurrentBounded == &(pNesting->pMapsAndArrays[i]) ? "->": " ",
549 i,
550 TypeStr(pNesting->pMapsAndArrays[i].uLevelType));
551
552 if(pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_BYTE_STRING) {
553 printf(" %5d %5d",
554 pNesting->pMapsAndArrays[i].u.bs.uEndOfBstr,
555 pNesting->pMapsAndArrays[i].u.bs.uPreviousEndOffset);
556
557 } else {
558 printf("%10.10s ",
559 CountString(pNesting->pMapsAndArrays[i].u.ma.uCountCursor,
560 pNesting->pMapsAndArrays[i].u.ma.uCountTotal));
561 if(pNesting->pMapsAndArrays[i].u.ma.uStartOffset != UINT32_MAX) {
562 printf("Bounded start: %u",pNesting->pMapsAndArrays[i].u.ma.uStartOffset);
563 }
564 }
565
566 printf("\n");
567 /*
568 TYPE
569 count/total
570 start offset/unbound
571 */
572
573/* printf("%2s %2d %5d %s %6u %5d %d %5d\n",
Laurence Lundblade02625d42020-06-25 14:41:41 -0700574 pNesting->pCurrentBounded == &(pNesting->pMapsAndArrays[i]) ? "->": " ",
575 i,
576 pNesting->pMapsAndArrays[i].u.ma.uCountCursor,
577 pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_MAP ? "map " :
578 (pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_ARRAY ? "array" :
579 (pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_BYTE_STRING ? "bstr " :
580 (pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_NONE ? "none " : "?????"))),
581 pNesting->pMapsAndArrays[i].u.ma.uStartOffset,
582 pNesting->pMapsAndArrays[i].u.ma.uCountTotal,
583 0, // TODO: fix this
584 pNesting->pMapsAndArrays[i].u.bs.uPreviousEndOffset
585 );
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700586*/
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700587 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700588 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700589}
590
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700591
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700592
Laurence Lundbladeee851742020-01-08 08:37:05 -0800593/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800594 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
595
596 The following four functions are pretty wrappers for invocation of
597 the string allocator supplied by the caller.
598
Laurence Lundbladeee851742020-01-08 08:37:05 -0800599 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800600
Laurence Lundbladeee851742020-01-08 08:37:05 -0800601static inline void
602StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800603{
604 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
605}
606
Laurence Lundbladeee851742020-01-08 08:37:05 -0800607// StringAllocator_Reallocate called with pMem NULL is
608// equal to StringAllocator_Allocate()
609static inline UsefulBuf
610StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
611 void *pMem,
612 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800613{
614 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
615}
616
Laurence Lundbladeee851742020-01-08 08:37:05 -0800617static inline UsefulBuf
618StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800619{
620 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
621}
622
Laurence Lundbladeee851742020-01-08 08:37:05 -0800623static inline void
624StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800625{
626 if(pMe->pfAllocator) {
627 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
628 }
629}
630
631
632
Laurence Lundbladeee851742020-01-08 08:37:05 -0800633/*===========================================================================
634 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700635
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800636 See qcbor/qcbor_decode.h for definition of the object
637 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800638 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639/*
640 Public function, see header file
641 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800642void QCBORDecode_Init(QCBORDecodeContext *me,
643 UsefulBufC EncodedCBOR,
644 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700645{
646 memset(me, 0, sizeof(QCBORDecodeContext));
647 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800648 // Don't bother with error check on decode mode. If a bad value is
649 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700650 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700651 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700652 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700653 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700654 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700655}
656
657
658/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700659 Public function, see header file
660 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800661void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
662 QCBORStringAllocate pfAllocateFunction,
663 void *pAllocateContext,
664 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700665{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800666 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
667 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
668 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700669}
670
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800671
672/*
673 Public function, see header file
674 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800675void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
676 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700677{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700678 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700679}
680
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700681
682/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800683 This decodes the fundamental part of a CBOR data item, the type and
684 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800685
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700686 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800687
Laurence Lundbladeee851742020-01-08 08:37:05 -0800688 This does the network->host byte order conversion. The conversion
689 here also results in the conversion for floats in addition to that
690 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800691
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700692 This returns:
693 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800694
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800695 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800696 tags and floats and length for strings and arrays
697
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800698 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800699 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800700
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800701 The int type is preferred to uint8_t for some variables as this
702 avoids integer promotions, can reduce code size and makes
703 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700704 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800705inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
706 int *pnMajorType,
707 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800708 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700709{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700710 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800711
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700712 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800713 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800714
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700715 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800716 const int nTmpMajorType = nInitialByte >> 5;
717 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800718
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800719 // Where the number or argument accumulates
720 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800721
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800722 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700723 // Need to get 1,2,4 or 8 additional argument bytes. Map
724 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800725 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800726
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800727 // Loop getting all the bytes in the argument
728 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800729 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800730 // This shift and add gives the endian conversion
731 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
732 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800733 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800734 // The reserved and thus-far unused additional info values
735 nReturn = QCBOR_ERR_UNSUPPORTED;
736 goto Done;
737 } else {
738 // Less than 24, additional info is argument or 31, an indefinite length
739 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800740 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700741 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800742
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700743 if(UsefulInputBuf_GetError(pUInBuf)) {
744 nReturn = QCBOR_ERR_HIT_END;
745 goto Done;
746 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800747
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700748 // All successful if we got here.
749 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800750 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800751 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800752 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800753
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700754Done:
755 return nReturn;
756}
757
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800758
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700759/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800760 CBOR doesn't explicitly specify two's compliment for integers but all
761 CPUs use it these days and the test vectors in the RFC are so. All
762 integers in the CBOR structure are positive and the major type
763 indicates positive or negative. CBOR can express positive integers
764 up to 2^x - 1 where x is the number of bits and negative integers
765 down to 2^x. Note that negative numbers can be one more away from
766 zero than positive. Stdint, as far as I can tell, uses two's
767 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800768
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700769 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800770 used carefully here, and in particular why it isn't used in the interface.
771 Also see
772 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
773
774 Int is used for values that need less than 16-bits and would be subject
775 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700776 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800777inline static QCBORError
778DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700779{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700780 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800781
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700782 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
783 if (uNumber <= INT64_MAX) {
784 pDecodedItem->val.int64 = (int64_t)uNumber;
785 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800786
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700787 } else {
788 pDecodedItem->val.uint64 = uNumber;
789 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800790
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700791 }
792 } else {
793 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800794 // CBOR's representation of negative numbers lines up with the
795 // two-compliment representation. A negative integer has one
796 // more in range than a positive integer. INT64_MIN is
797 // equal to (-INT64_MAX) - 1.
798 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700799 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800800
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700801 } else {
802 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000803 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700804 nReturn = QCBOR_ERR_INT_OVERFLOW;
805 }
806 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800807
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700808 return nReturn;
809}
810
811// Make sure #define value line up as DecodeSimple counts on this.
812#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
813#error QCBOR_TYPE_FALSE macro value wrong
814#endif
815
816#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
817#error QCBOR_TYPE_TRUE macro value wrong
818#endif
819
820#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
821#error QCBOR_TYPE_NULL macro value wrong
822#endif
823
824#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
825#error QCBOR_TYPE_UNDEF macro value wrong
826#endif
827
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700828#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
829#error QCBOR_TYPE_BREAK macro value wrong
830#endif
831
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700832#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
833#error QCBOR_TYPE_DOUBLE macro value wrong
834#endif
835
836#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
837#error QCBOR_TYPE_FLOAT macro value wrong
838#endif
839
840/*
841 Decode true, false, floats, break...
842 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800843inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800844DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700845{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700846 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800847
Laurence Lundbladeee851742020-01-08 08:37:05 -0800848 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800849 // above make sure uAdditionalInfo values line up with uDataType values.
850 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
851 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800852
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800853 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800854 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
855 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800856
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700857 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700858 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
859 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700860 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700861 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700862 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
863 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700864 break;
865 case DOUBLE_PREC_FLOAT:
866 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700867 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700868 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800869
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700870 case CBOR_SIMPLEV_FALSE: // 20
871 case CBOR_SIMPLEV_TRUE: // 21
872 case CBOR_SIMPLEV_NULL: // 22
873 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700874 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700875 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800876
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700877 case CBOR_SIMPLEV_ONEBYTE: // 24
878 if(uNumber <= CBOR_SIMPLE_BREAK) {
879 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700880 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700881 goto Done;
882 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800883 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700884 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800885
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700886 default: // 0-19
887 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800888 /*
889 DecodeTypeAndNumber will make uNumber equal to
890 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
891 safe because the 2, 4 and 8 byte lengths of uNumber are in
892 the double/float cases above
893 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700894 pDecodedItem->val.uSimple = (uint8_t)uNumber;
895 break;
896 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800897
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700898Done:
899 return nReturn;
900}
901
902
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700903/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530904 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700905 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800906inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
907 int nMajorType,
908 uint64_t uStrLen,
909 UsefulInputBuf *pUInBuf,
910 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700911{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700912 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800913
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800914 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
915 // This check makes the casts to size_t below safe.
916
917 // 4 bytes less than the largest sizeof() so this can be tested by
918 // putting a SIZE_MAX length in the CBOR test input (no one will
919 // care the limit on strings is 4 bytes shorter).
920 if(uStrLen > SIZE_MAX-4) {
921 nReturn = QCBOR_ERR_STRING_TOO_LONG;
922 goto Done;
923 }
924
925 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530926 if(UsefulBuf_IsNULLC(Bytes)) {
927 // Failed to get the bytes for this string item
928 nReturn = QCBOR_ERR_HIT_END;
929 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700930 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530931
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800932 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530933 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800934 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530935 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700936 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530937 goto Done;
938 }
939 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800940 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530941 } else {
942 // Normal case with no string allocator
943 pDecodedItem->val.string = Bytes;
944 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800945 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800946 // Cast because ternary operator causes promotion to integer
947 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
948 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800949
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530950Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700951 return nReturn;
952}
953
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700954
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800955
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700956
957
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700958
959
Laurence Lundbladeee851742020-01-08 08:37:05 -0800960// Make sure the constants align as this is assumed by
961// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700962#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
963#error QCBOR_TYPE_ARRAY value not lined up with major type
964#endif
965#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
966#error QCBOR_TYPE_MAP value not lined up with major type
967#endif
968
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700969/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800970 This gets a single data item and decodes it including preceding
971 optional tagging. This does not deal with arrays and maps and nesting
972 except to decode the data item introducing them. Arrays and maps are
973 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800974
Laurence Lundbladeee851742020-01-08 08:37:05 -0800975 Errors detected here include: an array that is too long to decode,
976 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700977 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800978static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
979 QCBORItem *pDecodedItem,
980 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700982 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800983
Laurence Lundbladeee851742020-01-08 08:37:05 -0800984 /*
985 Get the major type and the number. Number could be length of more
986 bytes or the value depending on the major type nAdditionalInfo is
987 an encoding of the length of the uNumber and is needed to decode
988 floats and doubles
989 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800990 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700991 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800992 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800993
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700994 memset(pDecodedItem, 0, sizeof(QCBORItem));
995
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800996 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800997
Laurence Lundbladeee851742020-01-08 08:37:05 -0800998 // Error out here if we got into trouble on the type and number. The
999 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001000 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001001 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001002 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001003
Laurence Lundbladeee851742020-01-08 08:37:05 -08001004 // At this point the major type and the value are valid. We've got
1005 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001006 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001007 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
1008 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001009 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001010 nReturn = QCBOR_ERR_BAD_INT;
1011 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001012 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001013 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001014 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001015
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001016 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
1017 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001018 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1019 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
1020 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
1021 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +05301022 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001023 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001024 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001025 }
1026 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001027
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001028 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
1029 case CBOR_MAJOR_TYPE_MAP: // Major type 5
1030 // Record the number of items in the array or map
1031 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
1032 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1033 goto Done;
1034 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001035 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001036 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001037 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001038 // type conversion OK because of check above
1039 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001040 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001041 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001042 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
1043 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001044 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001045
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001046 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001047 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001048 nReturn = QCBOR_ERR_BAD_INT;
1049 } else {
1050 pDecodedItem->val.uTagV = uNumber;
1051 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
1052 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001054
Laurence Lundbladeee851742020-01-08 08:37:05 -08001055 case CBOR_MAJOR_TYPE_SIMPLE:
1056 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001057 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001058 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001059
Laurence Lundbladeee851742020-01-08 08:37:05 -08001060 default:
1061 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001062 nReturn = QCBOR_ERR_UNSUPPORTED;
1063 break;
1064 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001065
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001066Done:
1067 return nReturn;
1068}
1069
1070
1071
1072/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001073 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001074 individual chunk items together into one QCBORItem using the string
1075 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001076
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301077 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001078 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001079static inline QCBORError
1080GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001081{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001082 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001083
1084 // Get pointer to string allocator. First use is to pass it to
1085 // GetNext_Item() when option is set to allocate for *every* string.
1086 // Second use here is to allocate space to coallese indefinite
1087 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001088 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1089 &(me->StringAllocator) :
1090 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001091
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001092 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001093 nReturn = GetNext_Item(&(me->InBuf),
1094 pDecodedItem,
1095 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001096 if(nReturn) {
1097 goto Done;
1098 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001099
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001100 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301101 // code in this function from here down can be eliminated. Run tests, except
1102 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001103
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001104 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001105 const uint8_t uStringType = pDecodedItem->uDataType;
1106 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001107 goto Done; // no need to do any work here on non-string types
1108 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001109
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001110 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301111 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001112 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001113 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001114
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301115 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001116 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001117 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1118 goto Done;
1119 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001120
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001121 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001122 UsefulBufC FullString = NULLUsefulBufC;
1123
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001124 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001125 // Get item for next chunk
1126 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001127 // NULL string allocator passed here. Do not need to allocate
1128 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001129 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001130 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001131 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001132 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001133
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301134 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001135 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001136 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001137 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301138 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001139 break;
1140 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001141
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001142 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301143 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001144 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001145 if(StringChunkItem.uDataType != uStringType ||
1146 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001147 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001148 break;
1149 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001150
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301151 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001152 // The first time throurgh FullString.ptr is NULL and this is
1153 // equivalent to StringAllocator_Allocate()
1154 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1155 UNCONST_POINTER(FullString.ptr),
1156 FullString.len + StringChunkItem.val.string.len);
1157
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001158 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301159 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001160 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001161 break;
1162 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001163
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001164 // Copy new string chunk at the end of string so far.
1165 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001166 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001167
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001168 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1169 // Getting the item failed, clean up the allocated memory
1170 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001171 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001172
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001173Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001174 return nReturn;
1175}
1176
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001177
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001178static uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1179 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001180 return uTagVal;
1181 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001182 int x = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001183 return me->auMappedTags[x];
1184 }
1185}
1186
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001187/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001188 Gets all optional tag data items preceding a data item that is not an
1189 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001190 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001191static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001192GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001193{
Laurence Lundblade30816f22018-11-10 13:40:22 +07001194 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001195
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001196 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1197 CBOR_TAG_INVALID16,
1198 CBOR_TAG_INVALID16,
1199 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001200
Laurence Lundblade59289e52019-12-30 13:44:37 -08001201 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001202 for(;;) {
1203 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001204 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001205 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001206 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001207
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001208 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1209 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001210 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001211 break;
1212 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001213
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001214 // Is there room for the tag in the tags list?
1215 size_t uTagIndex;
1216 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001217 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001218 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001219 }
1220 }
1221 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001222 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001223 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001224
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001225 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001226 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001227 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001228 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001229 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001230 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001231 break;
1232 }
1233 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001234 // TODO: test this
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001235 break;
1236 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001237 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001238 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1239 // No room for the tag
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001240 // Should never happen as long as QCBOR_MAX_TAGS_PER_ITEM <= QCBOR_NUM_MAPPED_TAGS
1241 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001242 }
1243
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001244 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001245 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001246 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001247
1248 } else {
1249 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001250 }
1251 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001252
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001253Done:
1254 return nReturn;
1255}
1256
1257
1258/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001259 This layer takes care of map entries. It combines the label and data
1260 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001261 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001262static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001263GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001264{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001265 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001266 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001267 if(nReturn)
1268 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001269
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001270 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001271 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001272 goto Done;
1273 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001274
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001275 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1276 // In a map and caller wants maps decoded, not treated as arrays
1277
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001278 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001279 // If in a map and the right decoding mode, get the label
1280
Laurence Lundbladeee851742020-01-08 08:37:05 -08001281 // Save label in pDecodedItem and get the next which will
1282 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001283 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001284 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001285 if(nReturn)
1286 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001287
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301288 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001289
1290 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1291 // strings are always good labels
1292 pDecodedItem->label.string = LabelItem.val.string;
1293 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1294 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001295 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001296 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1297 goto Done;
1298 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1299 pDecodedItem->label.int64 = LabelItem.val.int64;
1300 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1301 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1302 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1303 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1304 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1305 pDecodedItem->label.string = LabelItem.val.string;
1306 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1307 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1308 } else {
1309 // label is not an int or a string. It is an arrray
1310 // or a float or such and this implementation doesn't handle that.
1311 // Also, tags on labels are ignored.
1312 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1313 goto Done;
1314 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001315 }
1316 } else {
1317 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001318 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1319 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1320 goto Done;
1321 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001322 // Decoding a map as an array
1323 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001324 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1325 // Cast is needed because of integer promotion
1326 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001327 }
1328 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001329
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001330Done:
1331 return nReturn;
1332}
1333
1334
Laurence Lundblade02625d42020-06-25 14:41:41 -07001335/*
1336 See if next item is a CBOR break. If it is, it is consumed,
1337 if not it is not consumed.
1338*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001339static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001340NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1341{
1342 *pbNextIsBreak = false;
1343 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001344 QCBORItem Peek;
1345 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1346 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1347 if(uReturn != QCBOR_SUCCESS) {
1348 return uReturn;
1349 }
1350 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001351 // It is not a break, rewind so it can be processed normally.
1352 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001353 } else {
1354 *pbNextIsBreak = true;
1355 }
1356 }
1357
1358 return QCBOR_SUCCESS;
1359}
1360
1361
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001362/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001363 An item was just consumed, now figure out if it was the
1364 end of an array or map that can be closed out. That
1365 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001366*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001367static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool *pbHitBound)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001368{
1369 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001370
Laurence Lundblade642282a2020-06-23 12:00:33 -07001371 /* This loops ascending nesting levels as long as there is ascending to do */
1372 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1373
1374 if(DecodeNesting_IsDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001375 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001376 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1377 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001378 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001379 break;
1380 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001381 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001382
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001383 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001384 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001385 bool bIsBreak = false;
1386 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1387 if(uReturn != QCBOR_SUCCESS) {
1388 goto Done;
1389 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001390
1391 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001392 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001393 break;
1394 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001395
1396 if(DecodeNesting_IsBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001397 /*
1398 Break occurred inside a bstr-wrapped CBOR or
1399 in the top level sequence. This is always an
1400 error because neither are an indefinte length
1401 map/array.
1402 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001403 uReturn = QCBOR_ERR_BAD_BREAK;
1404 goto Done;
1405 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001406 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001407 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001408
Laurence Lundblade02625d42020-06-25 14:41:41 -07001409 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001410
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001411 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001412 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001413 /* Set the count to zero for definite length arrays to indicate cursor is at end of bounded map / array */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001414 if(pbHitBound) {
1415 *pbHitBound = true;
1416 }
1417 // Used for definite and indefinite to signal end
Laurence Lundblade02625d42020-06-25 14:41:41 -07001418 DecodeNesting_ZeroDefiniteLengthCount(&(pMe->nesting));
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001419 break;
1420 }
1421
1422 /* Finally, actually ascend one level. */
1423 DecodeNesting_Ascend(&(pMe->nesting));
1424 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001425
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001426 uReturn = QCBOR_SUCCESS;
1427
1428Done:
1429 return uReturn;
1430}
1431
1432
1433/*
Laurence Lundblade642282a2020-06-23 12:00:33 -07001434 This the travesal going descending into and asecnding out of maps,
1435 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1436 indefinte length maps and arrays by looking at the item count or
1437 finding CBOR breaks. It detects the ends of the top-level sequence
1438 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001439 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001440static QCBORError
1441QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001442{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001443 QCBORError uReturn;
Laurence Lundblade642282a2020-06-23 12:00:33 -07001444 /* ==== First figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001445
Laurence Lundblade642282a2020-06-23 12:00:33 -07001446 /*
1447 If out of bytes to consume, it is either the end of the top-level
1448 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001449
Laurence Lundblade642282a2020-06-23 12:00:33 -07001450 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1451 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1452 CBOR is exited, the length is set back to the top-level's length
1453 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001454
Laurence Lundblade642282a2020-06-23 12:00:33 -07001455 Only return the success error code QCBOR_ERR_NO_MORE_ITEMS here
1456 when at the top level to allow other code below to process various
1457 errors when out of bytes to decode and not at the top level. Note
1458 that QCBORDecode_Finish() still needs to be called to be sure all
1459 nesting levels were closed out.
1460 */
1461 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 &&
1462 DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001463 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001464 goto Done;
1465 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001466
Laurence Lundblade642282a2020-06-23 12:00:33 -07001467 /*
1468 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001469 array. The check for the end of an indefinite length array is
1470 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001471 */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001472 // TODO: this doesn't work for bounded indefinite length maps and arrays
Laurence Lundblade642282a2020-06-23 12:00:33 -07001473 if(DecodeNesting_IsAtEndOfBoundedDefiniteLenMapOrArray(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001474 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001475 goto Done;
1476 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001477
Laurence Lundblade642282a2020-06-23 12:00:33 -07001478 /* ==== Next, not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001479 uReturn = GetNext_MapEntry(me, pDecodedItem);
1480 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001481 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001482 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301483
Laurence Lundblade642282a2020-06-23 12:00:33 -07001484 /*
1485 Breaks ending arrays/maps are always processed at the end of this
1486 function. They should never show up here.
1487 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301488 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001489 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301490 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301491 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001492
Laurence Lundblade642282a2020-06-23 12:00:33 -07001493 /*
1494 Record the nesting level for this data item before processing any
1495 of decrementing and descending.
1496 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001497 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001498
Laurence Lundblade642282a2020-06-23 12:00:33 -07001499
1500 /* ==== Next, Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001501 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001502 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001503 If the new item is a map or array descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001504
Laurence Lundblade02625d42020-06-25 14:41:41 -07001505 Empty maps and arrays descended into, but then ascended out
1506 of in the next chunk of code.
1507
1508 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001509 encloses them so a decrement needs to be done for them too, but
1510 that is done only when all the items in them have been
1511 processed, not when they are opened with the exception of an
1512 empty map or array.
1513 */
1514 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1515 pDecodedItem->uDataType,
1516 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001517 if(uReturn != QCBOR_SUCCESS) {
1518 goto Done;
1519 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001520 }
1521
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001522 bool bHitBounded = false;
1523
Laurence Lundblade02625d42020-06-25 14:41:41 -07001524 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1525 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1526 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001527 /*
1528 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001529 - A non-aggregate like an integer or string
1530 - An empty definite length map or array
1531 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001532
1533 The Ascender does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001534 definite length map/array and break detection for an indefinite
1535 length map/array. If the end of the map/array was reached, then
1536 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001537 */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001538 uReturn = NestLevelAscender(me, &bHitBounded);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001539 if(uReturn) {
1540 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001541 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301542 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001543
Laurence Lundblade02625d42020-06-25 14:41:41 -07001544 /* ==== Last, tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001545 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001546 Tell the caller what level is next. This tells them what
1547 maps/arrays were closed out and makes it possible for them to
1548 reconstruct the tree with just the information returned in
1549 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001550 */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001551 if(DecodeNesting_IsAtEndOfBoundedFarf(&(me->nesting)) && bHitBounded) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001552 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001553 pDecodedItem->uNextNestLevel = 0;
1554 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001555 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001556 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001557
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001558Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001559 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001560 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001561 memset(pDecodedItem, 0, sizeof(QCBORItem));
1562 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001563 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001564}
1565
1566
Laurence Lundblade59289e52019-12-30 13:44:37 -08001567/*
1568 Mostly just assign the right data type for the date string.
1569 */
1570inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1571{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001572 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1573 return QCBOR_ERR_BAD_OPT_TAG;
1574 }
1575
1576 const UsefulBufC Temp = pDecodedItem->val.string;
1577 pDecodedItem->val.dateString = Temp;
1578 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1579 return QCBOR_SUCCESS;
1580}
1581
1582
1583/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001584 The epoch formatted date. Turns lots of different forms of encoding
1585 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001586 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001587static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001588{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001589 QCBORError nReturn = QCBOR_SUCCESS;
1590
1591 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1592
1593 switch (pDecodedItem->uDataType) {
1594
1595 case QCBOR_TYPE_INT64:
1596 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1597 break;
1598
1599 case QCBOR_TYPE_UINT64:
1600 if(pDecodedItem->val.uint64 > INT64_MAX) {
1601 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1602 goto Done;
1603 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001604 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001605 break;
1606
1607 case QCBOR_TYPE_DOUBLE:
1608 {
1609 // This comparison needs to be done as a float before
1610 // conversion to an int64_t to be able to detect doubles
1611 // that are too large to fit into an int64_t. A double
1612 // has 52 bits of preceision. An int64_t has 63. Casting
1613 // INT64_MAX to a double actually causes a round up which
1614 // is bad and wrong for the comparison because it will
1615 // allow conversion of doubles that can't fit into a
1616 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1617 // the cutoff point as if that rounds up in conversion to
1618 // double it will still be less than INT64_MAX. 0x7ff is
1619 // picked because it has 11 bits set.
1620 //
1621 // INT64_MAX seconds is on the order of 10 billion years,
1622 // and the earth is less than 5 billion years old, so for
1623 // most uses this conversion error won't occur even though
1624 // doubles can go much larger.
1625 //
1626 // Without the 0x7ff there is a ~30 minute range of time
1627 // values 10 billion years in the past and in the future
1628 // where this this code would go wrong.
1629 const double d = pDecodedItem->val.dfnum;
1630 if(d > (double)(INT64_MAX - 0x7ff)) {
1631 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1632 goto Done;
1633 }
1634 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1635 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1636 }
1637 break;
1638
1639 default:
1640 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1641 goto Done;
1642 }
1643 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1644
1645Done:
1646 return nReturn;
1647}
1648
1649
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001650/*
1651 Mostly just assign the right data type for the bignum.
1652 */
1653inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1654{
1655 // Stack Use: UsefulBuf 1 -- 16
1656 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1657 return QCBOR_ERR_BAD_OPT_TAG;
1658 }
1659 const UsefulBufC Temp = pDecodedItem->val.string;
1660 pDecodedItem->val.bigNum = Temp;
1661 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1662 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1663 : QCBOR_TYPE_NEGBIGNUM);
1664 return QCBOR_SUCCESS;
1665}
1666
1667
Laurence Lundblade59289e52019-12-30 13:44:37 -08001668#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1669/*
1670 Decode decimal fractions and big floats.
1671
1672 When called pDecodedItem must be the array that is tagged as a big
1673 float or decimal fraction, the array that has the two members, the
1674 exponent and mantissa.
1675
1676 This will fetch and decode the exponent and mantissa and put the
1677 result back into pDecodedItem.
1678 */
1679inline static QCBORError
1680QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1681{
1682 QCBORError nReturn;
1683
1684 // --- Make sure it is an array; track nesting level of members ---
1685 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1686 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1687 goto Done;
1688 }
1689
1690 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001691 // definite length arrays, but not for indefnite. Instead remember
1692 // the nesting level the two integers must be at, which is one
1693 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001694 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1695
1696 // --- Is it a decimal fraction or a bigfloat? ---
1697 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1698 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1699
1700 // --- Get the exponent ---
1701 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001702 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001703 if(nReturn != QCBOR_SUCCESS) {
1704 goto Done;
1705 }
1706 if(exponentItem.uNestingLevel != nNestLevel) {
1707 // Array is empty or a map/array encountered when expecting an int
1708 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1709 goto Done;
1710 }
1711 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1712 // Data arriving as an unsigned int < INT64_MAX has been converted
1713 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1714 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1715 // will be too large for this to handle and thus an error that will
1716 // get handled in the next else.
1717 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1718 } else {
1719 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1720 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1721 goto Done;
1722 }
1723
1724 // --- Get the mantissa ---
1725 QCBORItem mantissaItem;
1726 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1727 if(nReturn != QCBOR_SUCCESS) {
1728 goto Done;
1729 }
1730 if(mantissaItem.uNestingLevel != nNestLevel) {
1731 // Mantissa missing or map/array encountered when expecting number
1732 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1733 goto Done;
1734 }
1735 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1736 // Data arriving as an unsigned int < INT64_MAX has been converted
1737 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1738 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1739 // will be too large for this to handle and thus an error that
1740 // will get handled in an else below.
1741 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1742 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1743 // Got a good big num mantissa
1744 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1745 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001746 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1747 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1748 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001749 } else {
1750 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1751 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1752 goto Done;
1753 }
1754
1755 // --- Check that array only has the two numbers ---
1756 if(mantissaItem.uNextNestLevel == nNestLevel) {
1757 // Extra items in the decimal fraction / big num
1758 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1759 goto Done;
1760 }
1761
1762Done:
1763
1764 return nReturn;
1765}
1766#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1767
1768
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001769
1770/*
1771 */
1772inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1773{
1774 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1775 return QCBOR_ERR_BAD_OPT_TAG;
1776 }
1777 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1778 return QCBOR_SUCCESS;
1779}
1780
1781
1782inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1783{
1784 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1785 return QCBOR_ERR_BAD_OPT_TAG;
1786 }
1787 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1788 return QCBOR_SUCCESS;
1789}
1790
1791
1792inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1793{
1794 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1795 return QCBOR_ERR_BAD_OPT_TAG;
1796 }
1797 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1798 return QCBOR_SUCCESS;
1799}
1800
1801
1802inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1803{
1804 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1805 return QCBOR_ERR_BAD_OPT_TAG;
1806 }
1807 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1808 return QCBOR_SUCCESS;
1809}
1810
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001811inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1812{
1813 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1814 return QCBOR_ERR_BAD_OPT_TAG;
1815 }
1816 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1817 return QCBOR_SUCCESS;
1818}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001819
1820inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1821{
1822 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1823 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
1824 } else if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1825 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1826 } else {
1827 return QCBOR_ERR_BAD_OPT_TAG;
1828 }
1829 return QCBOR_SUCCESS;
1830}
1831
1832
1833/*
1834 */
1835inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1836{
1837 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1838 return QCBOR_ERR_BAD_OPT_TAG;
1839 }
1840 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1841 return QCBOR_SUCCESS;
1842}
1843
1844
Laurence Lundblade59289e52019-12-30 13:44:37 -08001845/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001846 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001847 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001848QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001849QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001850{
1851 QCBORError nReturn;
1852
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001853 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001854 if(nReturn != QCBOR_SUCCESS) {
1855 goto Done;
1856 }
1857
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001858 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1859 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001860
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001861 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001862 nReturn = DecodeDateString(pDecodedItem);
1863 break;
1864
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001865 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001866 nReturn = DecodeDateEpoch(pDecodedItem);
1867 break;
1868
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001869 case CBOR_TAG_POS_BIGNUM:
1870 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001871 nReturn = DecodeBigNum(pDecodedItem);
1872 break;
1873
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001874 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1875 case CBOR_TAG_DECIMAL_FRACTION:
1876 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001877 // For aggregate tagged types, what goes into pTags is only collected
1878 // from the surrounding data item, not the contents, so pTags is not
1879 // passed on here.
1880
1881 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1882 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001883 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001884
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001885 case CBOR_TAG_CBOR:
1886 nReturn = DecodeWrappedCBOR(pDecodedItem);
1887 break;
1888
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001889 case CBOR_TAG_URI:
1890 nReturn = DecodeURI(pDecodedItem);
1891 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001892
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001893 case CBOR_TAG_B64URL:
1894 nReturn = DecodeB64URL(pDecodedItem);
1895 break;
1896
1897 case CBOR_TAG_B64:
1898 nReturn = DecodeB64(pDecodedItem);
1899 break;
1900
1901 case CBOR_TAG_MIME:
1902 case CBOR_TAG_BINARY_MIME:
1903 nReturn = DecodeMIME(pDecodedItem);
1904 break;
1905
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001906 case CBOR_TAG_REGEX:
1907 nReturn = DecodeRegex(pDecodedItem);
1908 break;
1909
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001910 case CBOR_TAG_BIN_UUID:
1911 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001912 break;
1913
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001914 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001915 // The end of the tag list or no tags
1916 // Successful exit from the loop.
1917 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001918
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001919 default:
1920 // A tag that is not understood
1921 // A successful exit from the loop
1922 goto Done;
1923
1924 }
1925 if(nReturn != QCBOR_SUCCESS) {
1926 goto Done;
1927 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001928 }
1929
1930Done:
1931 if(nReturn != QCBOR_SUCCESS) {
1932 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1933 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1934 }
1935 return nReturn;
1936}
1937
1938
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001939QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1940{
1941 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1942
1943 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1944
1945 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1946
1947 return uErr;
1948}
1949
1950
Laurence Lundblade59289e52019-12-30 13:44:37 -08001951/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001952 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001953 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001954QCBORError
1955QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1956 QCBORItem *pDecodedItem,
1957 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001958{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001959 QCBORError nReturn;
1960
1961 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1962 if(nReturn != QCBOR_SUCCESS) {
1963 return nReturn;
1964 }
1965
1966 if(pTags != NULL) {
1967 pTags->uNumUsed = 0;
1968 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001969 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001970 break;
1971 }
1972 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1973 return QCBOR_ERR_TOO_MANY_TAGS;
1974 }
1975 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1976 pTags->uNumUsed++;
1977 }
1978 }
1979
1980 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001981}
1982
1983
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001984/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301985 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301986 next one down. If a layer has no work to do for a particular item
1987 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001988
Laurence Lundblade59289e52019-12-30 13:44:37 -08001989 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1990 tagged data items, turning them into the local C representation.
1991 For the most simple it is just associating a QCBOR_TYPE with the data. For
1992 the complex ones that an aggregate of data items, there is some further
1993 decoding and a little bit of recursion.
1994
1995 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301996 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301997 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001998 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001999
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302000 - GetNext_MapEntry -- This handles the combining of two
2001 items, the label and the data, that make up a map entry.
2002 It only does work on maps. It combines the label and data
2003 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002004
Laurence Lundblade59289e52019-12-30 13:44:37 -08002005 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2006 tags into bit flags associated with the data item. No actual decoding
2007 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002008
Laurence Lundblade59289e52019-12-30 13:44:37 -08002009 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302010 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302011 string allocater to create contiguous space for the item. It
2012 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002013
Laurence Lundblade59289e52019-12-30 13:44:37 -08002014 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2015 atomic data item has a "major type", an integer "argument" and optionally
2016 some content. For text and byte strings, the content is the bytes
2017 that make up the string. These are the smallest data items that are
2018 considered to be well-formed. The content may also be other data items in
2019 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002020
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002021 Roughly this takes 300 bytes of stack for vars. Need to
2022 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002023
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302024 */
2025
2026
2027/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002028 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002029 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002030int QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002031 const QCBORItem *pItem,
2032 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002033{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002034 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002035 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002036 break;
2037 }
2038 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
2039 return 1;
2040 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002041 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002042
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002043 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002044}
2045
2046
2047/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002048 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002049 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002050QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002051{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002052 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002053
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002054 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002055 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002056 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
2057 goto Done;
2058 }
2059
2060 // Error out if not all the bytes are consumed
2061 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
2062 nReturn = QCBOR_ERR_EXTRA_BYTES;
2063 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002064
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002065Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302066 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002067 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002068 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002069
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002070 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002071}
2072
2073
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002074/*
2075Public function, see header qcbor/qcbor_decode.h file
2076*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002077uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2078 const QCBORItem *pItem,
2079 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002080{
2081 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
2082 return CBOR_TAG_INVALID16;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002083 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002084 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002085 }
2086}
2087
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002088
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002089/*
2090
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002091Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002092
Laurence Lundbladeee851742020-01-08 08:37:05 -08002093 - Hit end of input before it was expected while decoding type and
2094 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002095
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002096 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002097
Laurence Lundbladeee851742020-01-08 08:37:05 -08002098 - Hit end of input while decoding a text or byte string
2099 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002100
Laurence Lundbladeee851742020-01-08 08:37:05 -08002101 - Encountered conflicting tags -- e.g., an item is tagged both a date
2102 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002103
Laurence Lundbladeee851742020-01-08 08:37:05 -08002104 - Encontered an array or mapp that has too many items
2105 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002106
Laurence Lundbladeee851742020-01-08 08:37:05 -08002107 - Encountered array/map nesting that is too deep
2108 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002109
Laurence Lundbladeee851742020-01-08 08:37:05 -08002110 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2111 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002112
Laurence Lundbladeee851742020-01-08 08:37:05 -08002113 - The type of a map label is not a string or int
2114 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002115
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002116 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002117
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002118 */
2119
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002120
2121
Laurence Lundbladef6531662018-12-04 10:42:22 +09002122
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002123/* ===========================================================================
2124 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002125
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002126 This implements a simple sting allocator for indefinite length
2127 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2128 implements the function type QCBORStringAllocate and allows easy
2129 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002130
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002131 This particular allocator is built-in for convenience. The caller
2132 can implement their own. All of this following code will get
2133 dead-stripped if QCBORDecode_SetMemPool() is not called.
2134
2135 This is a very primitive memory allocator. It does not track
2136 individual allocations, only a high-water mark. A free or
2137 reallocation must be of the last chunk allocated.
2138
2139 The size of the pool and offset to free memory are packed into the
2140 first 8 bytes of the memory pool so we don't have to keep them in
2141 the decode context. Since the address of the pool may not be
2142 aligned, they have to be packed and unpacked as if they were
2143 serialized data of the wire or such.
2144
2145 The sizes packed in are uint32_t to be the same on all CPU types
2146 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002147 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002148
2149
Laurence Lundbladeee851742020-01-08 08:37:05 -08002150static inline int
2151MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002152{
2153 // Use of UsefulInputBuf is overkill, but it is convenient.
2154 UsefulInputBuf UIB;
2155
Laurence Lundbladeee851742020-01-08 08:37:05 -08002156 // Just assume the size here. It was checked during SetUp so
2157 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002158 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2159 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2160 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2161 return UsefulInputBuf_GetError(&UIB);
2162}
2163
2164
Laurence Lundbladeee851742020-01-08 08:37:05 -08002165static inline int
2166MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002167{
2168 // Use of UsefulOutBuf is overkill, but convenient. The
2169 // length check performed here is useful.
2170 UsefulOutBuf UOB;
2171
2172 UsefulOutBuf_Init(&UOB, Pool);
2173 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2174 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2175 return UsefulOutBuf_GetError(&UOB);
2176}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002177
2178
2179/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002180 Internal function for an allocation, reallocation free and destuct.
2181
2182 Having only one function rather than one each per mode saves space in
2183 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002184
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002185 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2186 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002187static UsefulBuf
2188MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002189{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002190 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002191
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002192 uint32_t uPoolSize;
2193 uint32_t uFreeOffset;
2194
2195 if(uNewSize > UINT32_MAX) {
2196 // This allocator is only good up to 4GB. This check should
2197 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2198 goto Done;
2199 }
2200 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2201
2202 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2203 goto Done;
2204 }
2205
2206 if(uNewSize) {
2207 if(pMem) {
2208 // REALLOCATION MODE
2209 // Calculate pointer to the end of the memory pool. It is
2210 // assumed that pPool + uPoolSize won't wrap around by
2211 // assuming the caller won't pass a pool buffer in that is
2212 // not in legitimate memory space.
2213 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2214
2215 // Check that the pointer for reallocation is in the range of the
2216 // pool. This also makes sure that pointer math further down
2217 // doesn't wrap under or over.
2218 if(pMem >= pPool && pMem < pPoolEnd) {
2219 // Offset to start of chunk for reallocation. This won't
2220 // wrap under because of check that pMem >= pPool. Cast
2221 // is safe because the pool is always less than UINT32_MAX
2222 // because of check in QCBORDecode_SetMemPool().
2223 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2224
2225 // Check to see if the allocation will fit. uPoolSize -
2226 // uMemOffset will not wrap under because of check that
2227 // pMem is in the range of the uPoolSize by check above.
2228 if(uNewSize <= uPoolSize - uMemOffset) {
2229 ReturnValue.ptr = pMem;
2230 ReturnValue.len = uNewSize;
2231
2232 // Addition won't wrap around over because uNewSize was
2233 // checked to be sure it is less than the pool size.
2234 uFreeOffset = uMemOffset + uNewSize32;
2235 }
2236 }
2237 } else {
2238 // ALLOCATION MODE
2239 // uPoolSize - uFreeOffset will not underflow because this
2240 // pool implementation makes sure uFreeOffset is always
2241 // smaller than uPoolSize through this check here and
2242 // reallocation case.
2243 if(uNewSize <= uPoolSize - uFreeOffset) {
2244 ReturnValue.len = uNewSize;
2245 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002246 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002247 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002248 }
2249 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002250 if(pMem) {
2251 // FREE MODE
2252 // Cast is safe because of limit on pool size in
2253 // QCBORDecode_SetMemPool()
2254 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2255 } else {
2256 // DESTRUCT MODE
2257 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002258 }
2259 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002260
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002261 UsefulBuf Pool = {pPool, uPoolSize};
2262 MemPool_Pack(Pool, uFreeOffset);
2263
2264Done:
2265 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002266}
2267
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002268
Laurence Lundbladef6531662018-12-04 10:42:22 +09002269/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002270 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002271 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002272QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2273 UsefulBuf Pool,
2274 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002275{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002276 // The pool size and free mem offset are packed into the beginning
2277 // of the pool memory. This compile time check make sure the
2278 // constant in the header is correct. This check should optimize
2279 // down to nothing.
2280 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002281 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002282 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002283
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002284 // The pool size and free offset packed in to the beginning of pool
2285 // memory are only 32-bits. This check will optimize out on 32-bit
2286 // machines.
2287 if(Pool.len > UINT32_MAX) {
2288 return QCBOR_ERR_BUFFER_TOO_LARGE;
2289 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002290
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002291 // This checks that the pool buffer given is big enough.
2292 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2293 return QCBOR_ERR_BUFFER_TOO_SMALL;
2294 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002295
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002296 pMe->StringAllocator.pfAllocator = MemPool_Function;
2297 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2298 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002299
Laurence Lundblade30816f22018-11-10 13:40:22 +07002300 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002301}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002302
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002303
2304
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002305
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002306
2307
2308/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002309 Consume an entire map or array (and do next to
2310 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002311 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002312static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002313ConsumeItem(QCBORDecodeContext *pMe,
2314 const QCBORItem *pItemToConsume,
2315 uint_fast8_t *puNextNestLevel)
2316{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002317 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002318 QCBORItem Item;
2319
Laurence Lundblade02625d42020-06-25 14:41:41 -07002320 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002321
Laurence Lundblade02625d42020-06-25 14:41:41 -07002322 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002323 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002324
Laurence Lundblade1341c592020-04-11 14:19:05 -07002325 /* This works for definite and indefinite length
2326 * maps and arrays by using the nesting level
2327 */
2328 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002329 uReturn = QCBORDecode_GetNext(pMe, &Item);
2330 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002331 goto Done;
2332 }
2333 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002334
Laurence Lundblade1341c592020-04-11 14:19:05 -07002335 if(puNextNestLevel != NULL) {
2336 *puNextNestLevel = Item.uNextNestLevel;
2337 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002338 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002339
Laurence Lundblade1341c592020-04-11 14:19:05 -07002340 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002341 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002342 if(puNextNestLevel != NULL) {
2343 /* Just pass the nesting level through */
2344 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2345 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002346 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002347 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002348
2349Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002350 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002351}
2352
2353
Laurence Lundblade1341c592020-04-11 14:19:05 -07002354/* Return true if the labels in Item1 and Item2 are the same.
2355 Works only for integer and string labels. Returns false
2356 for any other type. */
2357static inline bool
2358MatchLabel(QCBORItem Item1, QCBORItem Item2)
2359{
2360 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2361 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2362 return true;
2363 }
2364 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002365 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002366 return true;
2367 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002368 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002369 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2370 return true;
2371 }
2372 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2373 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2374 return true;
2375 }
2376 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002377
Laurence Lundblade1341c592020-04-11 14:19:05 -07002378 /* Other label types are never matched */
2379 return false;
2380}
2381
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002382
2383/*
2384 Returns true if Item1 and Item2 are the same type
2385 or if either are of QCBOR_TYPE_ANY.
2386 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002387static inline bool
2388MatchType(QCBORItem Item1, QCBORItem Item2)
2389{
2390 if(Item1.uDataType == Item2.uDataType) {
2391 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002392 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002393 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002394 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002395 return true;
2396 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002397 return false;
2398}
2399
2400
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002401/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002402 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002403
2404 @param[in] pMe The decode context to search.
2405 @param[in,out] pItemArray The items to search for and the items found.
2406 @param[in] pCBContext Context for the not-found item call back
2407 @param[in] pfCallback Function to call on items not matched in pItemArray
2408
2409 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2410
2411 @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.
2412
2413 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2414
2415 @retval Also errors returned by QCBORDecode_GetNext().
2416
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002417 On input pItemArray contains a list of labels and data types
2418 of items to be found.
2419
2420 On output the fully retrieved items are filled in with
2421 values and such. The label was matched, so it never changes.
2422
2423 If an item was not found, its data type is set to none.
2424
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002425 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002426static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002427MapSearch(QCBORDecodeContext *pMe,
2428 QCBORItem *pItemArray,
2429 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002430 void *pCBContext,
2431 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002432{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002433 QCBORError uReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002434
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002435 QCBORDecodeNesting SaveNesting;
2436 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002437
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002438 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002439 UsefulInputBuf_Seek(&(pMe->InBuf),
2440 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002441
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002442 /*
2443 Loop over all the items in the map. They could be
2444 deeply nested and this should handle both definite
2445 and indefinite length maps and arrays, so this
2446 adds some complexity.
2447 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002448 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002449
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002450 uint_fast8_t uNextNestLevel;
2451
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002452 uint64_t uFoundItemBitMap = 0;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002453
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002454 /* Iterate over items in the map / array */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002455 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002456 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002457 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002458
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002459 /* Get the item */
2460 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002461 uReturn = QCBORDecode_GetNext(pMe, &Item);
2462 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002463 /* Got non-well-formed CBOR */
2464 goto Done;
2465 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002466
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002467 /* See if item has one of the labels that are of interest */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002468 int nIndex;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002469 QCBORItem *pIterator;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002470 for(pIterator = pItemArray, nIndex = 0; pIterator->uLabelType != 0; pIterator++, nIndex++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002471 if(MatchLabel(Item, *pIterator)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002472 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002473 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2474 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002475 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002476 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002477 /* Also try to match its type */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002478 if(!MatchType(Item, *pIterator)) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002479 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002480 goto Done;
2481 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002482
2483 /* Successful match. Return the item. */
2484 *pIterator = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002485 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002486 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002487 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002488 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002489 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002490 /*
2491 Call the callback on unmatched labels.
2492 (It is tempting to do duplicate detection here, but that would
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002493 require dynamic memory allocation because the number of labels
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002494 that might be encountered is unbounded.)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002495 */
2496 if(pfCallback) {
2497 uReturn = (*pfCallback)(pCBContext, &Item);
2498 if(uReturn != QCBOR_SUCCESS) {
2499 goto Done;
2500 }
2501 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002502 }
2503 }
2504
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002505 /*
2506 Consume the item whether matched or not. This
2507 does the work of traversing maps and array and
2508 everything in them. In this loop only the
2509 items at the current nesting level are examined
2510 to match the labels.
2511 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002512 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2513 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002514 goto Done;
2515 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002516
2517 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002518
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002519 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002520
2521 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002522 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2523 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002524
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002525 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002526 int i;
2527 QCBORItem *pIterator;
2528 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002529 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002530 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002531 }
2532 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002533
2534Done:
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002535 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002536
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002537 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002538}
2539
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002540
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002541/*
2542Public function, see header qcbor/qcbor_decode.h file
2543*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002544void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2545 int64_t nLabel,
2546 uint8_t uQcborType,
2547 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002548{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002549 if(pMe->uLastError != QCBOR_SUCCESS) {
2550 return;
2551 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002552
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002553 QCBORItem OneItemSeach[2];
2554 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2555 OneItemSeach[0].label.int64 = nLabel;
2556 OneItemSeach[0].uDataType = uQcborType;
2557 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002558
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002559 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002560 if(nReturn) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002561 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002562 }
2563
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002564 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
2565 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002566 }
2567
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002568 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002569}
2570
2571
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002572/*
2573Public function, see header qcbor/qcbor_decode.h file
2574*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002575void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2576 const char *szLabel,
2577 uint8_t uQcborType,
2578 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002579{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002580 if(pMe->uLastError != QCBOR_SUCCESS) {
2581 return;
2582 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002583
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002584 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002585 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2586 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2587 OneItemSeach[0].uDataType = uQcborType;
2588 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002589
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002590 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002591 if(nReturn) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002592 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002593 }
2594
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002595 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002596 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002597 }
2598
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002599 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002600}
2601
2602
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002603/**
2604 @param[in] TagSpec Specification for matching tags.
2605 @param[in] uDataType A QCBOR data type
2606
2607 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2608 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2609
2610 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2611 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002612static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002613{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002614 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
2615 /* Must match the tag */
2616 if(uDataType == TagSpec.uTaggedType) {
2617 return QCBOR_SUCCESS;
2618 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002619 } else {
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002620 /* QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE or QCBOR_TAGSPEC_MATCH_EITHER */
2621 /* Must check all the possible types for the tag content */
2622 for(size_t i = 0; i < sizeof(TagSpec.uAllowedContentTypes); i++) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002623 if(uDataType == TagSpec.uAllowedContentTypes[i]) {
2624 return QCBOR_SUCCESS;
2625 }
2626 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002627 /* Didn't match any of the tag content types */
2628 /* Check the tag for the either case */
2629 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_EITHER) {
2630 if(uDataType == TagSpec.uTaggedType) {
2631 return QCBOR_SUCCESS;
2632 }
2633 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002634 }
2635
2636 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002637}
2638
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002639
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002640// Semi-private
2641// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002642void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2643 int64_t nLabel,
2644 TagSpecification TagSpec,
2645 QCBORItem *pItem)
2646{
2647 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2648 if(pMe->uLastError != QCBOR_SUCCESS) {
2649 return;
2650 }
2651
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002652 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002653}
2654
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002655// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002656void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2657 const char *szLabel,
2658 TagSpecification TagSpec,
2659 QCBORItem *pItem)
2660{
2661 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2662 if(pMe->uLastError != QCBOR_SUCCESS) {
2663 return;
2664 }
2665
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002666 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002667}
2668
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002669// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002670void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2671 int64_t nLabel,
2672 TagSpecification TagSpec,
2673 UsefulBufC *pString)
2674{
2675 QCBORItem Item;
2676 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2677 if(pMe->uLastError == QCBOR_SUCCESS) {
2678 *pString = Item.val.string;
2679 }
2680}
2681
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002682// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002683void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2684 const char * szLabel,
2685 TagSpecification TagSpec,
2686 UsefulBufC *pString)
2687{
2688 QCBORItem Item;
2689 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2690 if(pMe->uLastError == QCBOR_SUCCESS) {
2691 *pString = Item.val.string;
2692 }
2693}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002694
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002695/*
2696Public function, see header qcbor/qcbor_decode.h file
2697*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002698QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2699{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002700 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002701}
2702
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002703/*
2704Public function, see header qcbor/qcbor_decode.h file
2705*/
2706QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2707 QCBORItem *pItemList,
2708 void *pCallbackCtx,
2709 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002710{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002711 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002712}
2713
2714
Laurence Lundblade34691b92020-05-18 22:25:25 -07002715static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002716{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002717 if(pMe->uLastError != QCBOR_SUCCESS) {
2718 // Already in error state; do nothing.
2719 return;
2720 }
2721
2722 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002723 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002724 if(pMe->uLastError != QCBOR_SUCCESS) {
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
2731 Also need to current map nesting level and start cursor to
2732 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
2739 However the map mode nesting level is assumed to be one above
2740 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 Lundblade0750fc42020-06-20 21:02:34 -07002744 pMe->nesting.pCurrent = pMe->nesting.pCurrentBounded; // TODO: part of DecodeNesting
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002745
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002746 QCBORDecode_EnterBoundedMode(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002747}
2748
2749
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002750/*
2751Public function, see header qcbor/qcbor_decode.h file
2752*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002753void QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002754{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002755 QCBORItem OneItemSeach[2];
2756 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2757 OneItemSeach[0].label.int64 = nLabel;
2758 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2759 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002760
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002761 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002762 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002763}
2764
2765
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002766/*
2767Public function, see header qcbor/qcbor_decode.h file
2768*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002769void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002770{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002771 QCBORItem OneItemSeach[2];
2772 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2773 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2774 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2775 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002776
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002777 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002778}
2779
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002780/*
2781Public function, see header qcbor/qcbor_decode.h file
2782*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002783void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002784{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002785 QCBORItem OneItemSeach[2];
2786 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2787 OneItemSeach[0].label.int64 = nLabel;
2788 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2789 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002790
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002791 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002792}
2793
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002794/*
2795Public function, see header qcbor/qcbor_decode.h file
2796*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002797void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2798{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002799 QCBORItem OneItemSeach[2];
2800 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2801 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2802 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2803 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002804
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002805 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002806}
2807
2808
Laurence Lundblade02625d42020-06-25 14:41:41 -07002809// Semi-private function
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002810/* Next item must be map or this generates an error */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002811void QCBORDecode_EnterBoundedMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002812{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002813 if(pMe->uLastError != QCBOR_SUCCESS) {
2814 // Already in error state; do nothing.
2815 return;
2816 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002817
2818 /* Get the data item that is the map that is being searched */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002819 QCBORItem Item;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002820 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002821 if(pMe->uLastError != QCBOR_SUCCESS) {
2822 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002823 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002824 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002825 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2826 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002827 }
2828
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002829 DecodeNesting_EnterBoundedMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002830
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002831 // TODO: restrict input to less than this or some other invalidation strategy.
Laurence Lundblade02625d42020-06-25 14:41:41 -07002832 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002833
Laurence Lundblade02625d42020-06-25 14:41:41 -07002834 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002835}
2836
Laurence Lundblade02625d42020-06-25 14:41:41 -07002837
2838/*
2839 This is for exiting a level that is a bounded map, array or bstr
2840 wrapped CBOR. It is the work common to these.
2841
2842 One chunk of work is to set up the pre-order traversal so it is at
2843 the item just after the bounded map, array or bstr that is being
2844 exited. This is somewhat complex.
2845
2846 The other work is to level-up the bounded mode to next higest bounded
2847 mode or the top level if there isn't one.
2848 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002849static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002850ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002851{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002852 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002853
Laurence Lundblade02625d42020-06-25 14:41:41 -07002854 /*
2855 First the pre-order-traversal byte offset is positioned to the
2856 item just after the bounded mode item that was just consumed.
2857 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002858 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2859
Laurence Lundblade02625d42020-06-25 14:41:41 -07002860 /*
2861 Next, set the current nesting level to one above the bounded level
2862 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002863
Laurence Lundblade02625d42020-06-25 14:41:41 -07002864 DecodeNesting_CheckBoundedType() is always called before this and
2865 makes sure pCurrentBounded is valid.
2866 */
2867 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2868
2869 /*
2870 This does the complex work of leveling up the pre-order traversal
2871 when the end of a map or array or another bounded level is
2872 reached. It may do nothing, or ascend all the way to the top
2873 level.
2874 */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002875 uErr = NestLevelAscender(pMe, NULL);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002876 if(uErr != QCBOR_SUCCESS) {
2877 goto Done;
2878 }
2879
Laurence Lundblade02625d42020-06-25 14:41:41 -07002880 /*
2881 This makes the next highest bounded level the current bounded
2882 level. If there is no next highest level, then no bounded mode is
2883 in effect.
2884 */
2885 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002886
Laurence Lundblade02625d42020-06-25 14:41:41 -07002887 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002888
2889Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002890 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002891 return uErr;
2892}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002893
Laurence Lundblade02625d42020-06-25 14:41:41 -07002894
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002895// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002896void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002897{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002898 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002899 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002900 return;
2901 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002902
Laurence Lundblade02625d42020-06-25 14:41:41 -07002903 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002904
Laurence Lundblade02625d42020-06-25 14:41:41 -07002905 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002906 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2907 goto Done;
2908 }
2909
Laurence Lundblade02625d42020-06-25 14:41:41 -07002910 /*
2911 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002912 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002913 from previous map search, then do a dummy search.
2914 */
2915 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002916 QCBORItem Dummy;
2917 Dummy.uLabelType = QCBOR_TYPE_NONE;
2918 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2919 if(uErr != QCBOR_SUCCESS) {
2920 goto Done;
2921 }
2922 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002923
Laurence Lundblade02625d42020-06-25 14:41:41 -07002924 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002925
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002926Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002927 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002928}
2929
2930
Laurence Lundblade1341c592020-04-11 14:19:05 -07002931void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002932{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002933 // TODO: check for map mode; test this
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002934 //pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->u.ma.uCountTotal;
2935 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->u.ma.uStartOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002936}
2937
2938
Laurence Lundblade1341c592020-04-11 14:19:05 -07002939
Laurence Lundblade02625d42020-06-25 14:41:41 -07002940static QCBORError InternalEnterWrappedBstr(QCBORDecodeContext *pMe,
2941 const QCBORItem *pItem,
2942 uint8_t uTagRequirement,
2943 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002944{
2945 if(pMe->uLastError != QCBOR_SUCCESS) {
2946 // Already in error state; do nothing.
2947 return pMe->uLastError;
2948 }
2949
2950 QCBORError uError = QCBOR_SUCCESS;
2951
2952 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2953 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2954 goto Done;;
2955 }
2956
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002957 // TODO: check for the other wrapped CBOR tag
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002958 const TagSpecification TagSpec = {uTagRequirement, QBCOR_TYPE_WRAPPED_CBOR, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
2959
2960 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2961 if(uError != QCBOR_SUCCESS) {
2962 goto Done;
2963 }
2964
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002965 if(DecodeNesting_IsDefiniteLength(&(pMe->nesting))) {
2966 /* Reverse the decrement done by GetNext() for the bstr as
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002967 so the increment in NestLevelAscender called by ExitBoundedLevel()
2968 will work right. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002969 // TODO: method for this
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002970 pMe->nesting.pCurrent->u.ma.uCountCursor++;
2971 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002972
2973 if(pBstr) {
2974 *pBstr = pItem->val.string;
2975 }
2976
2977 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002978
2979 // Need to move UIB input cursor to the right place
2980
2981 // Really this is a subtraction and an assignment; not much code
2982 // There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002983 // The bstr was just consumed so the cursor is at the next item after it
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002984
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002985 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002986
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002987
2988 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
2989
2990 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002991
Laurence Lundblade02625d42020-06-25 14:41:41 -07002992 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
2993 uPreviousLength,
2994 uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002995Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002996 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002997
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002998 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002999}
3000
3001
Laurence Lundblade02625d42020-06-25 14:41:41 -07003002/*
3003 Public function, see header qcbor/qcbor_decode.h file
3004 */
3005void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
3006 uint8_t uTagRequirement,
3007 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003008{
3009 if(pMe->uLastError != QCBOR_SUCCESS) {
3010 // Already in error state; do nothing.
3011 return;
3012 }
3013
3014 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003015 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003016 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3017 if(pMe->uLastError != QCBOR_SUCCESS) {
3018 return;
3019 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003020
Laurence Lundblade02625d42020-06-25 14:41:41 -07003021 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe,
3022 &Item,
3023 uTagRequirement,
3024 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003025}
3026
3027
Laurence Lundblade02625d42020-06-25 14:41:41 -07003028/*
3029 Public function, see header qcbor/qcbor_decode.h file
3030 */
3031void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
3032 uint8_t uTagRequirement,
3033 int64_t nLabel,
3034 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003035{
3036 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003037 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003038
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003039 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003040}
3041
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003042
Laurence Lundblade02625d42020-06-25 14:41:41 -07003043/*
3044 Public function, see header qcbor/qcbor_decode.h file
3045 */
3046void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
3047 uint8_t uTagRequirement,
3048 const char *szLabel,
3049 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003050{
3051 QCBORItem Item;
3052 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3053
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003054 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003055}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003056
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003057
Laurence Lundblade02625d42020-06-25 14:41:41 -07003058/*
3059 Public function, see header qcbor/qcbor_decode.h file
3060 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003061void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003062{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003063 if(pMe->uLastError != QCBOR_SUCCESS) {
3064 // Already in error state; do nothing.
3065 return;
3066 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003067
Laurence Lundblade02625d42020-06-25 14:41:41 -07003068 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3069 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
3070 return;
3071 }
3072
3073 /*
3074 Reset the length of the UsefulInputBuf to what it was before
3075 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003076 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003077 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
3078 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003079
3080
Laurence Lundblade02625d42020-06-25 14:41:41 -07003081 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003082 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003083}
3084
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003085
Laurence Lundbladee6430642020-03-14 21:15:44 -07003086
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003087
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003088
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003089
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003090
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003091
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003092static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3093{
3094 switch(pItem->uDataType) {
3095 case QCBOR_TYPE_TRUE:
3096 *pBool = true;
3097 return QCBOR_SUCCESS;
3098 break;
3099
3100 case QCBOR_TYPE_FALSE:
3101 *pBool = false;
3102 return QCBOR_SUCCESS;
3103 break;
3104
3105 default:
3106 return QCBOR_ERR_UNEXPECTED_TYPE;
3107 break;
3108 }
3109}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003110
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003111/*
3112Public function, see header qcbor/qcbor_decode.h file
3113*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003114void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003115{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003116 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003117 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003118 return;
3119 }
3120
Laurence Lundbladec4537442020-04-14 18:53:22 -07003121 QCBORError nError;
3122 QCBORItem Item;
3123
3124 nError = QCBORDecode_GetNext(pMe, &Item);
3125 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003126 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003127 return;
3128 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003129 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003130}
3131
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003132/*
3133Public function, see header qcbor/qcbor_decode.h file
3134*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003135void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003136{
3137 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003138 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003139
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003140 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003141}
3142
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003143/*
3144Public function, see header qcbor/qcbor_decode.h file
3145*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003146void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3147{
3148 QCBORItem Item;
3149 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3150
3151 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3152}
3153
3154
3155
3156void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003157{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003158 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003159 // Already in error state, do nothing
3160 return;
3161 }
3162
3163 QCBORError nError;
3164 QCBORItem Item;
3165
3166 nError = QCBORDecode_GetNext(pMe, &Item);
3167 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003168 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003169 return;
3170 }
3171
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003172 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3173
3174 if(pMe->uLastError == QCBOR_SUCCESS) {
3175 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003176 }
3177}
3178
Laurence Lundbladec4537442020-04-14 18:53:22 -07003179
3180
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003181
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003182static QCBORError ConvertBigNum(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003183{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003184 *pbIsNegative = false;
3185
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003186 bool bMustBeTagged = true; // TODO: fix this --- they have to tell us if they are expecting positive or negative
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003187
3188 switch(pItem->uDataType) {
3189 case QCBOR_TYPE_BYTE_STRING:
3190 // TODO: check that there is no tag here?
3191 if(bMustBeTagged) {
3192 return QCBOR_ERR_UNEXPECTED_TYPE;
3193 } else {
3194 *pValue = pItem->val.string;
3195 return QCBOR_SUCCESS;
3196 }
3197 break;
3198
3199 case QCBOR_TYPE_POSBIGNUM:
3200 *pValue = pItem->val.string;
3201 return QCBOR_SUCCESS;
3202 break;
3203
3204 case QCBOR_TYPE_NEGBIGNUM:
3205 *pbIsNegative = true;
3206 *pValue = pItem->val.string;
3207 return QCBOR_SUCCESS;
3208 break;
3209
3210 default:
3211 return QCBOR_ERR_UNEXPECTED_TYPE;
3212 break;
3213 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003214}
3215
3216
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003217/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003218 @param[in] bMustBeTagged If \c true, then the data item must be tagged as either
3219 a positive or negative bignum. If \c false, then it only must be a byte string and bIsNegative
3220 will always be false on the asumption that it is positive, but it can be interpretted as
3221 negative if the the sign is know from other context.
3222 @param[out] pValue The bytes that make up the big num
3223 @param[out] pbIsNegative \c true if tagged as a negative big num. \c false otherwise.
3224
3225 if bMustBeTagged is false, then this will succeed if the data item is a plain byte string,
3226 a positive big num or a negative big num.
3227
3228 */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003229void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003230{
3231 if(pMe->uLastError != QCBOR_SUCCESS) {
3232 // Already in error state, do nothing
3233 return;
3234 }
3235
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003236 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003237 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3238 if(uError != QCBOR_SUCCESS) {
3239 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003240 return;
3241 }
3242
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003243 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003244}
3245
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003246/*
3247Public function, see header qcbor/qcbor_decode.h file
3248*/
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003249void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003250{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003251 QCBORItem Item;
3252 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003253
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003254 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003255}
3256
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003257/*
3258Public function, see header qcbor/qcbor_decode.h file
3259*/
3260void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
3261{
3262 QCBORItem Item;
3263 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3264
3265 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
3266}
3267
3268
3269
3270// Semi private
3271QCBORError FarfMIME(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsNot7Bit)
3272{
3273 const TagSpecification TagSpecText = {uTagRequirement, QCBOR_TYPE_MIME, {QCBOR_TYPE_TEXT_STRING, 0,0,0,0,0}};
3274 const TagSpecification TagSpecBinary = {uTagRequirement, QCBOR_TYPE_BINARY_MIME, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
3275
3276 QCBORError uReturn;
3277
3278 if(CheckTagRequirement(TagSpecText, pItem->uDataType)) {
3279 *pMessage = pItem->val.string;
3280 if(pbIsNot7Bit != NULL) {
3281 *pbIsNot7Bit = false;
3282 }
3283 uReturn = QCBOR_SUCCESS;
3284 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType)) {
3285 *pMessage = pItem->val.string;
3286 if(pbIsNot7Bit != NULL) {
3287 *pbIsNot7Bit = true;
3288 }
3289 uReturn = QCBOR_SUCCESS;
3290
3291 } else {
3292 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3293 }
3294
3295 return uReturn;
3296}
3297
3298
3299
3300
3301
Laurence Lundbladec4537442020-04-14 18:53:22 -07003302
3303
3304
Laurence Lundbladee6430642020-03-14 21:15:44 -07003305
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003306typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003307
3308
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003309// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003310static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003311{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003312 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003313
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003314 if(uResult != 0) {
3315 /* This loop will run a maximum of 19 times because
3316 * UINT64_MAX < 10 ^^ 19. More than that will cause
3317 * exit with the overflow error
3318 */
3319 for(; nExponent > 0; nExponent--) {
3320 if(uResult > UINT64_MAX / 10) {
3321 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3322 }
3323 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003324 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003325
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003326 for(; nExponent < 0; nExponent++) {
3327 uResult = uResult / 10;
3328 if(uResult == 0) {
3329 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3330 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003331 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003332 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003333 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003334
3335 *puResult = uResult;
3336
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003337 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003338}
3339
3340
Laurence Lundbladee6430642020-03-14 21:15:44 -07003341/* Convert a decimal fraction to an int64_t without using
3342 floating point or math libraries. Most decimal fractions
3343 will not fit in an int64_t and this will error out with
3344 under or overflow
3345 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003346static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003347{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003348 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003349
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003350 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003351
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003352 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003353 * INT64_MAX < 2^31. More than that will cause
3354 * exist with the overflow error
3355 */
3356 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003357 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003358 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003359 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003360 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003361 nExponent--;
3362 }
3363
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003364 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003365 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003366 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3367 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003368 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003369 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003370 }
3371
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003372 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003373
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003374 return QCBOR_SUCCESS;
3375}
3376
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003377/*
3378 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3379 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003380static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3381{
3382 uint64_t uResult;
3383
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003384 // Take the absolute value of the mantissa and convert to unsigned.
3385 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003386 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3387
3388 // Do the exponentiation of the positive mantissa
3389 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3390 if(uReturn) {
3391 return uReturn;
3392 }
3393
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003394
Laurence Lundblade983500d2020-05-14 11:49:34 -07003395 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3396 of INT64_MIN. This assumes two's compliment representation where
3397 INT64_MIN is one increment farther from 0 than INT64_MAX.
3398 Trying to write -INT64_MIN doesn't work to get this because the
3399 compiler tries to work with an int64_t which can't represent
3400 -INT64_MIN.
3401 */
3402 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3403
3404 // Error out if too large
3405 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003406 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3407 }
3408
3409 // Casts are safe because of checks above
3410 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3411
3412 return QCBOR_SUCCESS;
3413}
3414
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003415/*
3416 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3417 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003418static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3419{
3420 if(nMantissa < 0) {
3421 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3422 }
3423
3424 // Cast to unsigned is OK because of check for negative
3425 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3426 // Exponentiation is straight forward
3427 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3428}
3429
3430
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003431#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003432
3433
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003434static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003435{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003436 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003437
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003438 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003439 const uint8_t *pByte = BigNum.ptr;
3440 size_t uLen = BigNum.len;
3441 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003442 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003443 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003444 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003445 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003446 }
3447
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003448 *pResult = uResult;
3449 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003450}
3451
Laurence Lundblade887add82020-05-17 05:50:34 -07003452static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003453{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003454 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003455}
3456
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003457static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003458{
3459 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003460 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3461 if(uError) {
3462 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003463 }
3464 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3465 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003466 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003467}
3468
3469
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003470static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003471{
3472 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003473 /* negaative int furthest from zero is INT64_MIN
3474 which is expressed as -INT64_MAX-1. The value of
3475 a negative bignum is -n-1, one further from zero
3476 than the positive bignum */
3477
3478 /* say INT64_MIN is -2; then INT64_MAX is 1.
3479 Then -n-1 <= INT64_MIN.
3480 Then -n -1 <= -INT64_MAX - 1
3481 THen n <= INT64_MAX. */
3482 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003483 if(uError) {
3484 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003485 }
3486 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003487 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003488 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003489 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003490 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003491}
3492
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003493#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003494
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003495
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003496/*
3497Convert a integers and floats to an int64_t.
3498
3499\param[in] uOptions Bit mask list of conversion options.
3500
3501\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3502
3503\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3504
3505\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3506
3507*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003508static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3509{
3510 switch(pItem->uDataType) {
3511 // TODO: float when ifdefs are set
3512 case QCBOR_TYPE_DOUBLE:
3513 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3514 // TODO: what about under/overflow here?
3515 // Invokes the floating-point HW and/or compiler-added libraries
3516 feclearexcept(FE_ALL_EXCEPT);
3517 *pnValue = llround(pItem->val.dfnum);
3518 if(fetestexcept(FE_INVALID)) {
3519 // TODO: better error code
3520 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3521 }
3522 } else {
3523 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3524 }
3525 break;
3526
3527 case QCBOR_TYPE_INT64:
3528 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3529 *pnValue = pItem->val.int64;
3530 } else {
3531 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3532 }
3533 break;
3534
3535 case QCBOR_TYPE_UINT64:
3536 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3537 if(pItem->val.uint64 < INT64_MAX) {
3538 *pnValue = pItem->val.int64;
3539 } else {
3540 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3541 }
3542 } else {
3543 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3544 }
3545 break;
3546
3547 default:
3548 return QCBOR_ERR_UNEXPECTED_TYPE;
3549 }
3550 return QCBOR_SUCCESS;
3551}
3552
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003553
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003554void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
3555 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003556 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003557 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003558{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003559 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003560 return;
3561 }
3562
Laurence Lundbladee6430642020-03-14 21:15:44 -07003563 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003564 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3565 if(uError) {
3566 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003567 return;
3568 }
3569
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003570 if(pItem) {
3571 *pItem = Item;
3572 }
3573
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003574 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003575}
3576
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003577
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003578void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3579 int64_t nLabel,
3580 uint32_t uOptions,
3581 int64_t *pnValue,
3582 QCBORItem *pItem)
3583{
3584 QCBORItem Item;
3585 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3586
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003587 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003588}
3589
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003590
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003591void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3592 const char * szLabel,
3593 uint32_t uOptions,
3594 int64_t *pnValue,
3595 QCBORItem *pItem)
3596{
3597 if(pMe->uLastError != QCBOR_SUCCESS) {
3598 return;
3599 }
3600
3601 QCBORItem Item;
3602 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3603
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003604 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003605}
3606
3607
3608
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003609/*
3610 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003611
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003612 \param[in] uOptions Bit mask list of conversion options.
3613
3614 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3615
3616 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3617
3618 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3619
3620 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003621static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3622{
3623 QCBORError uErr;
3624
3625 switch(pItem->uDataType) {
3626
3627 case QCBOR_TYPE_POSBIGNUM:
3628 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3629 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003630 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003631 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003632 }
3633 break;
3634
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003635 case QCBOR_TYPE_NEGBIGNUM:
3636 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3637 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003638 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003639 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003640 }
3641 break;
3642
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003643#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3644 case QCBOR_TYPE_DECIMAL_FRACTION:
3645 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3646 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3647 pItem->val.expAndMantissa.nExponent,
3648 pnValue,
3649 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003650 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003651 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3652 }
3653 break;
3654
3655 case QCBOR_TYPE_BIGFLOAT:
3656 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3657 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3658 pItem->val.expAndMantissa.nExponent,
3659 pnValue,
3660 Exponentitate2);
3661 } else {
3662 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3663 }
3664 break;
3665
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003666 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3667 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3668 int64_t nMantissa;
3669 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3670 if(uErr) {
3671 return uErr;
3672 }
3673 return ExponentiateNN(nMantissa,
3674 pItem->val.expAndMantissa.nExponent,
3675 pnValue,
3676 Exponentitate10);
3677 } else {
3678 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3679 }
3680 break;
3681
3682 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3683 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3684 int64_t nMantissa;
3685 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3686 if(uErr) {
3687 return uErr;
3688 }
3689 return ExponentiateNN(nMantissa,
3690 pItem->val.expAndMantissa.nExponent,
3691 pnValue,
3692 Exponentitate10);
3693 } else {
3694 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3695 }
3696 break;
3697
3698 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3699 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3700 int64_t nMantissa;
3701 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3702 if(uErr) {
3703 return uErr;
3704 }
3705 return ExponentiateNN(nMantissa,
3706 pItem->val.expAndMantissa.nExponent,
3707 pnValue,
3708 Exponentitate2);
3709 } else {
3710 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3711 }
3712 break;
3713
3714 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3715 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3716 int64_t nMantissa;
3717 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3718 if(uErr) {
3719 return uErr;
3720 }
3721 return ExponentiateNN(nMantissa,
3722 pItem->val.expAndMantissa.nExponent,
3723 pnValue,
3724 Exponentitate2);
3725 } else {
3726 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003727 }
3728 break;
3729
Laurence Lundbladec4537442020-04-14 18:53:22 -07003730 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003731 return QCBOR_ERR_UNEXPECTED_TYPE;
3732#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07003733 }
3734}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003735
3736
Laurence Lundbladec4537442020-04-14 18:53:22 -07003737/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003738 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003739 */
3740void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003741{
3742 QCBORItem Item;
3743
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003744 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003745
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003746 if(pMe->uLastError == QCBOR_SUCCESS) {
3747 // The above conversion succeeded
3748 return;
3749 }
3750
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003751 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003752 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003753 return;
3754 }
3755
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003756 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003757}
3758
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003759
3760/*
3761Public function, see header qcbor/qcbor_decode.h file
3762*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003763void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
3764{
3765 QCBORItem Item;
3766
3767 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
3768
3769 if(pMe->uLastError == QCBOR_SUCCESS) {
3770 // The above conversion succeeded
3771 return;
3772 }
3773
3774 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3775 // The above conversion failed in a way that code below can't correct
3776 return;
3777 }
3778
3779 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3780}
3781
3782
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003783/*
3784Public function, see header qcbor/qcbor_decode.h file
3785*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003786void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3787{
3788 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003789 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3790
3791 if(pMe->uLastError == QCBOR_SUCCESS) {
3792 // The above conversion succeeded
3793 return;
3794 }
3795
3796 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3797 // The above conversion failed in a way that code below can't correct
3798 return;
3799 }
3800
3801 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3802}
3803
3804
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003805static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3806{
3807 switch(pItem->uDataType) {
3808 // TODO: type flaot
3809 case QCBOR_TYPE_DOUBLE:
3810 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3811 feclearexcept(FE_ALL_EXCEPT);
3812 double dRounded = round(pItem->val.dfnum);
3813 // TODO: over/underflow
3814 if(fetestexcept(FE_INVALID)) {
3815 // TODO: better error code
3816 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3817 } else if(isnan(dRounded)) {
3818 // TODO: better error code
3819 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3820 } else if(dRounded >= 0) {
3821 *puValue = (uint64_t)dRounded;
3822 } else {
3823 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3824 }
3825 } else {
3826 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3827 }
3828 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003829
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003830 case QCBOR_TYPE_INT64:
3831 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3832 if(pItem->val.int64 >= 0) {
3833 *puValue = (uint64_t)pItem->val.int64;
3834 } else {
3835 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3836 }
3837 } else {
3838 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3839 }
3840 break;
3841
3842 case QCBOR_TYPE_UINT64:
3843 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3844 *puValue = pItem->val.uint64;
3845 } else {
3846 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3847 }
3848 break;
3849
3850 default:
3851 return QCBOR_ERR_UNEXPECTED_TYPE;
3852 }
3853 return QCBOR_SUCCESS;
3854}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003855
3856
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003857void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3858 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003859 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003860 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003861{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003862 if(pMe->uLastError != QCBOR_SUCCESS) {
3863 return;
3864 }
3865
Laurence Lundbladec4537442020-04-14 18:53:22 -07003866 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003867
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003868 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3869 if(uError) {
3870 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003871 return;
3872 }
3873
Laurence Lundbladea826c502020-05-10 21:07:00 -07003874 if(pItem) {
3875 *pItem = Item;
3876 }
3877
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003878 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003879}
3880
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003881
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003882void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3883{
3884 int64_t uValue;
3885 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, &uValue, pItem);
3886 if(pMe->uLastError != QCBOR_SUCCESS) {
3887 return;
3888 }
3889
3890 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3891 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3892 }
3893}
3894
3895void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3896{
3897 int64_t uValue;
3898 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, &uValue, pItem);
3899 if(pMe->uLastError != QCBOR_SUCCESS) {
3900 return;
3901 }
3902
3903 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3904 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3905 }
3906}
3907
3908void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3909{
3910 int64_t uValue;
3911 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, &uValue, pItem);
3912 if(pMe->uLastError != QCBOR_SUCCESS) {
3913 return;
3914 }
3915
3916 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3917 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3918 }
3919}
3920
3921
3922
3923
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003924void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3925 int64_t nLabel,
3926 uint32_t uOptions,
3927 uint64_t *puValue,
3928 QCBORItem *pItem)
3929{
3930 QCBORItem Item;
3931 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3932
3933 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3934}
3935
3936
3937void QCBORDecode_GetUint64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3938 const char * szLabel,
3939 uint32_t uOptions,
3940 uint64_t *puValue,
3941 QCBORItem *pItem)
3942{
3943 if(pMe->uLastError != QCBOR_SUCCESS) {
3944 return;
3945 }
3946
3947 QCBORItem Item;
3948 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3949
3950 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3951}
3952
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003953/*
3954 Public function, see header qcbor/qcbor_decode.h file
3955*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003956static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3957{
3958 QCBORError uErr;
3959
3960 switch(pItem->uDataType) {
3961
3962 case QCBOR_TYPE_POSBIGNUM:
3963 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3964 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3965 } else {
3966 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3967 }
3968 break;
3969
3970 case QCBOR_TYPE_NEGBIGNUM:
3971 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3972 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3973 } else {
3974 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3975 }
3976 break;
3977
3978#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3979
3980 case QCBOR_TYPE_DECIMAL_FRACTION:
3981 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3982 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3983 pItem->val.expAndMantissa.nExponent,
3984 puValue,
3985 Exponentitate10);
3986 } else {
3987 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3988 }
3989 break;
3990
3991 case QCBOR_TYPE_BIGFLOAT:
3992 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3993 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3994 pItem->val.expAndMantissa.nExponent,
3995 puValue,
3996 Exponentitate2);
3997 } else {
3998 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3999 }
4000 break;
4001
4002 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4003 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4004 // TODO: Would be better to convert to unsigned
4005 int64_t nMantissa;
4006 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4007 if(uErr != QCBOR_SUCCESS) {
4008 return uErr;
4009 }
4010 return ExponentitateNU(nMantissa,
4011 pItem->val.expAndMantissa.nExponent,
4012 puValue,
4013 Exponentitate10);
4014 } else {
4015 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4016 }
4017 break;
4018
4019 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4020 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4021 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4022 } else {
4023 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4024 }
4025 break;
4026
4027 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4028 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4029 // TODO: Would be better to convert to unsigned
4030 int64_t nMantissa;
4031 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4032 if(uErr != QCBOR_SUCCESS) {
4033 return uErr;
4034 }
4035 return ExponentitateNU(nMantissa,
4036 pItem->val.expAndMantissa.nExponent,
4037 puValue,
4038 Exponentitate2);
4039 } else {
4040 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4041 }
4042 break;
4043
4044 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4045 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4046 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4047 } else {
4048 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4049 }
4050 break;
4051#endif
4052 default:
4053 return QCBOR_ERR_UNEXPECTED_TYPE;
4054 }
4055}
4056
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004057/*
4058 Public function, see header qcbor/qcbor_decode.h file
4059*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004060void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004061{
4062 QCBORItem Item;
4063
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004064 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004065
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004066 if(pMe->uLastError == QCBOR_SUCCESS) {
4067 // The above conversion succeeded
4068 return;
4069 }
4070
4071 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4072 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004073 return;
4074 }
4075
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004076 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004077}
4078
Laurence Lundbladec4537442020-04-14 18:53:22 -07004079
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004080/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004081 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004082*/
4083void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
4084{
4085 QCBORItem Item;
4086
4087 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
4088
4089 if(pMe->uLastError == QCBOR_SUCCESS) {
4090 // The above conversion succeeded
4091 return;
4092 }
4093
4094 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4095 // The above conversion failed in a way that code below can't correct
4096 return;
4097 }
4098
4099 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4100}
4101
4102
4103/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004104 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004105*/
4106void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
4107{
4108 QCBORItem Item;
4109 QCBORDecode_GetUint64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
4110
4111 if(pMe->uLastError == QCBOR_SUCCESS) {
4112 // The above conversion succeeded
4113 return;
4114 }
4115
4116 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4117 // The above conversion failed in a way that code below can't correct
4118 return;
4119 }
4120
4121 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4122}
4123
4124
4125static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
4126{
4127 switch(pItem->uDataType) {
4128 // TODO: float when ifdefs are set
4129 case QCBOR_TYPE_DOUBLE:
4130 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4131 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4132 *pdValue = pItem->val.dfnum;
4133 } else {
4134 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4135 }
4136 }
4137 break;
4138
4139 case QCBOR_TYPE_INT64:
4140 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
4141 // TODO: how does this work?
4142 *pdValue = (double)pItem->val.int64;
4143
4144 } else {
4145 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4146 }
4147 break;
4148
4149 case QCBOR_TYPE_UINT64:
4150 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
4151 *pdValue = (double)pItem->val.uint64;
4152 } else {
4153 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4154 }
4155 break;
4156
4157 default:
4158 return QCBOR_ERR_UNEXPECTED_TYPE;
4159 }
4160
4161 return QCBOR_SUCCESS;
4162}
4163
4164
4165
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004166void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
4167 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004168 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004169 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004170{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004171 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004172 return;
4173 }
4174
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004175 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004176
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004177 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004178 if(uError) {
4179 pMe->uLastError = (uint8_t)uError;
4180 return;
4181 }
4182
4183 if(pItem) {
4184 *pItem = Item;
4185 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004186
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004187 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004188}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004189
Laurence Lundbladec4537442020-04-14 18:53:22 -07004190
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004191void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4192 int64_t nLabel,
4193 uint32_t uOptions,
4194 double *pdValue,
4195 QCBORItem *pItem)
4196{
4197 QCBORItem Item;
4198 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4199
4200 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4201}
4202
4203void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4204 const char * szLabel,
4205 uint32_t uOptions,
4206 double *pdValue,
4207 QCBORItem *pItem)
4208{
4209 if(pMe->uLastError != QCBOR_SUCCESS) {
4210 return;
4211 }
4212
4213 QCBORItem Item;
4214 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4215
4216 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4217}
4218
4219
4220
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004221static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4222{
4223 double dResult;
4224
4225 dResult = 0.0;
4226 const uint8_t *pByte = BigNum.ptr;
4227 size_t uLen = BigNum.len;
4228 /* This will overflow and become the float value INFINITY if the number
4229 is too large to fit. No error will be logged.
4230 TODO: should an error be logged? */
4231 while(uLen--) {
4232 dResult = (dResult * 256.0) + (double)*pByte++;
4233 }
4234
4235 return dResult;
4236}
4237
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004238static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004239{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004240 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004241 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4242
4243 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004244 switch(pItem->uDataType) {
4245 // TODO: type float
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004246
4247#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004248 case QCBOR_TYPE_DECIMAL_FRACTION:
4249 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4250 // TODO: rounding and overflow errors
4251 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4252 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4253 } else {
4254 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4255 }
4256 break;
4257
4258 case QCBOR_TYPE_BIGFLOAT:
4259 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
4260 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4261 exp2((double)pItem->val.expAndMantissa.nExponent);
4262 } else {
4263 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4264 }
4265 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004266#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004267
4268 case QCBOR_TYPE_POSBIGNUM:
4269 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
4270 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4271 } else {
4272 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4273 }
4274 break;
4275
4276 case QCBOR_TYPE_NEGBIGNUM:
4277 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004278 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004279 } else {
4280 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4281 }
4282 break;
4283
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004284#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004285 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4286 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4287 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4288 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4289 } else {
4290 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4291 }
4292 break;
4293
4294 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4295 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4296 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4297 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4298 } else {
4299 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4300 }
4301 break;
4302
4303 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4304 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
4305 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4306 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4307 } else {
4308 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4309 }
4310 break;
4311
4312 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4313 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004314 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004315 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4316 } else {
4317 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4318 }
4319 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004320#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4321
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004322
4323 default:
4324 return QCBOR_ERR_UNEXPECTED_TYPE;
4325 }
4326
4327 return QCBOR_SUCCESS;
4328}
4329
4330
4331/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004332 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004333*/
4334void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
4335{
4336
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004337 QCBORItem Item;
4338
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004339 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004340
4341 if(pMe->uLastError == QCBOR_SUCCESS) {
4342 // The above conversion succeeded
4343 return;
4344 }
4345
4346 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4347 // The above conversion failed in a way that code below can't correct
4348 return;
4349 }
4350
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004351 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004352}
4353
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004354
4355/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004356 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004357*/
4358void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
4359{
4360 QCBORItem Item;
4361
4362 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
4363
4364 if(pMe->uLastError == QCBOR_SUCCESS) {
4365 // The above conversion succeeded
4366 return;
4367 }
4368
4369 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4370 // The above conversion failed in a way that code below can't correct
4371 return;
4372 }
4373
4374 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4375}
4376
4377
4378/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004379 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004380*/
4381void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
4382{
4383 QCBORItem Item;
4384 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
4385
4386 if(pMe->uLastError == QCBOR_SUCCESS) {
4387 // The above conversion succeeded
4388 return;
4389 }
4390
4391 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4392 // The above conversion failed in a way that code below can't correct
4393 return;
4394 }
4395
4396 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4397}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004398
4399
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004400#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004401void FarfDecimalFraction(QCBORDecodeContext *pMe,
4402 uint8_t uTagRequirement,
4403 QCBORItem *pItem,
4404 int64_t *pnMantissa,
4405 int64_t *pnExponent)
4406{
4407 QCBORError uErr;
4408
4409 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
4410 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4411 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4412 return;
4413 }
4414 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4415 if(uErr != QCBOR_SUCCESS) {
4416 pMe->uLastError = (uint8_t)uErr;
4417 return;
4418 }
4419 }
4420
4421 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4422 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4423 return;
4424 }
4425
4426 switch (pItem->uDataType) {
4427
4428 case QCBOR_TYPE_DECIMAL_FRACTION:
4429 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4430 *pnExponent = pItem->val.expAndMantissa.nExponent;
4431 break;
4432
4433 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4434 *pnExponent = pItem->val.expAndMantissa.nExponent;
4435
4436 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4437 if(uErr != QCBOR_SUCCESS) {
4438 pMe->uLastError = (uint8_t)uErr;
4439 }
4440 break;
4441
4442 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4443 *pnExponent = pItem->val.expAndMantissa.nExponent;
4444
4445 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4446 if(uErr != QCBOR_SUCCESS) {
4447 pMe->uLastError = (uint8_t)uErr;
4448 }
4449 break;
4450
4451 default:
4452 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4453 }
4454}
4455
4456void QCBORDecode_GetDecimalFractionN(QCBORDecodeContext *pMe,
4457 uint8_t uTagRequirement,
4458 int64_t nLabel,
4459 int64_t *pnMantissa,
4460 int64_t *pnExponent)
4461{
4462 QCBORItem Item;
4463
4464 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4465 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4466}
4467
4468
4469
4470void QCBORDecode_GetDecimalFractionSZ(QCBORDecodeContext *pMe,
4471 uint8_t uTagRequirement,
4472 const char *szLabel,
4473 int64_t *pnMantissa,
4474 int64_t *pnExponent)
4475{
4476 QCBORItem Item;
4477
4478 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4479
4480 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4481}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004482#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004483
4484
4485UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4486{
4487 while(uInt & 0xff0000000000UL) {
4488 uInt = uInt << 8;
4489 };
4490
4491 UsefulOutBuf UOB;
4492
4493 UsefulOutBuf_Init(&UOB, Buffer);
4494
4495 while(uInt) {
4496 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56));
4497 uInt = uInt << 8;
4498 }
4499
4500 return UsefulOutBuf_OutUBuf(&UOB);
4501}
4502
4503
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004504#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4505
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004506void QCBORDecode_GetDecimalFractionBigN(QCBORDecodeContext *pMe,
4507 uint8_t uTagRequirement,
4508 int64_t nLabel,
4509 UsefulBuf pBufferForMantissa,
4510 UsefulBufC *pMantissa,
4511 bool *pbIsNegative,
4512 int64_t *pnExponent)
4513{
4514 QCBORItem Item;
4515 QCBORError uErr;
4516
4517 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4518
4519 if(Item.uDataType == QCBOR_TYPE_ARRAY) {
4520 uErr = QCBORDecode_MantissaAndExponent(pMe, &Item);
4521 if(uErr != QCBOR_SUCCESS) {
4522 pMe->uLastError = (uint8_t)uErr;
4523 return;
4524 }
4525 }
4526
4527 uint64_t uMantissa;
4528
4529 switch (Item.uDataType) {
4530
4531 case QCBOR_TYPE_DECIMAL_FRACTION:
4532 if(Item.val.expAndMantissa.Mantissa.nInt >= 0) {
4533 uMantissa = (uint64_t)Item.val.expAndMantissa.Mantissa.nInt;
4534 *pbIsNegative = false;
4535 } else {
4536 uMantissa = (uint64_t)-Item.val.expAndMantissa.Mantissa.nInt;
4537 *pbIsNegative = true;
4538 }
4539 *pMantissa = ConvertIntToBigNum(uMantissa, pBufferForMantissa);
4540 *pnExponent = Item.val.expAndMantissa.nExponent;
4541 break;
4542
4543 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4544 *pnExponent = Item.val.expAndMantissa.nExponent;
4545 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4546 *pbIsNegative = false;
4547 break;
4548
4549 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4550 *pnExponent = Item.val.expAndMantissa.nExponent;
4551 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4552 *pbIsNegative = true;
4553 break;
4554
4555 default:
4556 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4557 }
4558}
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004559#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */