blob: f5995fe8efd3b9c17d49b5ac352a9cf40fd25dff [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 Lundbladeee851742020-01-08 08:37:05 -080046/*===========================================================================
47 DecodeNesting -- Functions for tracking array/map nesting when decoding
48
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080049 See qcbor/qcbor_decode.h for definition of the object
50 used here: QCBORDecodeNesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080051 ===========================================================================*/
52
Laurence Lundblade9c905e82020-04-25 11:31:38 -070053
54
55/*
56The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...)
57formed by intermediate nodes (arrays and maps). The cursor for the traversal
58 is the byte offset in the encoded input and a leaf counter for definite
59 length maps and arrays. Indefinite length maps and arrays are handled
60 by look ahead for the break.
61
62 The view presented to the caller has tags, labels and the chunks of
63 indefinite length strings aggregated into one decorated data item.
64
65The caller understands the nesting level in pre-order traversal by
66 the fact that a data item that is a map or array is presented to
67 the caller when it is first encountered in the pre-order traversal and that all data items are presented with its nesting level
68 and the nesting level of the next item.
69
70 The caller traverse maps and arrays in a special mode that often more convenient
71 that tracking by nesting level. When an array or map is expected or encountered
72 the EnterMap or EnteryArray can be called.
73
74 When entering a map or array like this, the cursor points to the first
75 item in the map or array. When exiting, it points to the item after
76 the map or array, regardless of whether the items in the map or array were
77 all traversed.
78
79 When in a map or array, the cursor functions as normal, but traversal
80 cannot go past the end of the map or array that was entered. If this
81 is attempted the QCBOR_ERR_NO_MORE_ITEMS error is returned. To
82 go past the end of the map or array ExitMap() or ExitArray() must
83 be called. It can be called any time regardless of the position
84 of the cursor.
85
86 When a map is entered, a special function allows fetching data items
87 by label. This call will traversal the whole map looking for the
88 labeled item. The whole map is traversed so as to detect duplicates.
89 This type of fetching items does not affect the normal traversal
90 cursor.
91
92
93
94
95
96
97
98
99
100
101When a data item is presented to the caller, the nesting level of the data
102 item is presented along with the nesting level of the item that would be
103 next consumed.
104
105
106
107
108
109
110
111
112
113 */
114
Laurence Lundblade6b249302020-04-30 12:38:12 -0700115inline static bool
116// TODO: test Map as array better?
Laurence Lundbladeee851742020-01-08 08:37:05 -0800117IsMapOrArray(uint8_t uDataType)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700118{
Laurence Lundblade6b249302020-04-30 12:38:12 -0700119 return uDataType == QCBOR_TYPE_MAP ||
120 uDataType == QCBOR_TYPE_ARRAY ||
121 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700122}
123
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700124inline static bool
125DecodeNesting_IsAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700126{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700127 if(pNesting->pCurrent == &(pNesting->pMapsAndArrays[0])) {
128 return true;
129 } else {
130 return false;
131 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700132}
133
Laurence Lundblade937ea812020-05-08 11:38:23 -0700134// Determine if at the end of a map or array while in map mode
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700135inline static bool
136DecodeNesting_AtEnd(const QCBORDecodeNesting *pNesting)
137{
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700138 if(pNesting->pCurrentMap && pNesting->pCurrentMap->uMapMode) {
139 if(pNesting->pCurrentMap->uCount == 0) {
Laurence Lundblade937ea812020-05-08 11:38:23 -0700140 // TODO: won't work for indefinite length
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700141 // In map mode and consumed all items, so it is the end
142 return true;
143 } else {
144 // In map mode, all items not consumed, so it is NOT the end
145 return false;
146 }
147 } else {
Laurence Lundblade937ea812020-05-08 11:38:23 -0700148 // Not in map mode. The end is determined in other ways.
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700149 return false;
150 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700151}
152
153
Laurence Lundbladeee851742020-01-08 08:37:05 -0800154inline static int
155DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700156{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700157 return pNesting->pCurrent->uCount == UINT16_MAX;
158}
159
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700160inline static int
161DecodeNesting_InMapMode(const QCBORDecodeNesting *pNesting)
162{
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700163 return (bool)pNesting->pCurrentMap->uMapMode;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700164}
165
Laurence Lundbladeee851742020-01-08 08:37:05 -0800166inline static uint8_t
167DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800168{
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800169 // Check in DecodeNesting_Descend and never having
Laurence Lundbladebb87be22020-04-09 19:15:32 -0700170 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800171 return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800172}
173
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700174inline static uint8_t
175DecodeNesting_GetMapModeLevel(QCBORDecodeNesting *pNesting)
176{
177 // Check in DecodeNesting_Descend and never having
178 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
179 return (uint8_t)(pNesting->pCurrentMap - &(pNesting->pMapsAndArrays[0]));
180}
181
Laurence Lundbladeee851742020-01-08 08:37:05 -0800182inline static int
183DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700184{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700185 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700186 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700187 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800188
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700189 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
190}
191
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800192// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800193inline static QCBORError
194DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700195{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800196 // breaks must always occur when there is nesting
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700197 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800198 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700199 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800200
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800201 // breaks can only occur when the map/array is indefinite length
202 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
203 return QCBOR_ERR_BAD_BREAK;
204 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800205
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800206 // if all OK, the break reduces the level of nesting
207 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800208
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800209 return QCBOR_SUCCESS;
210}
211
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700212// Called on every single item except breaks including decode of a map/array
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700213/* Decrements the map/array counter if possible. If decrement
214 closed out a map or array, then level up in nesting and decrement
215 again, until, the top is reached or the end of a map mode is reached
216 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800217inline static void
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700218DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800219{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700220 while(!DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700221 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800222
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800223 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700224 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800225 pNesting->pCurrent->uCount--;
226 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700227
228 if(pNesting->pCurrent->uCount != 0) {
229 // Did not close out an array or map, so nothing further
230 break;
231 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700232
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700233 if(pNesting->pCurrent->uMapMode) {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700234 // In map mode the level-up must be done explicitly
235 break;
236 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700237
238 // Closed out an array or map so level up
239 pNesting->pCurrent--;
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700240 /*if(pNesting->pCurrent->uMapMode) {
241 // Bring the current map level along if new level is a map
242 // TODO: must search up until a mapmode level is found.
243 pNesting->pCurrentMap = pNesting->pCurrent;
244 } */
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700245
246 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700247 }
248}
249
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700250inline static void
251DecodeNesting_EnterMapMode(QCBORDecodeNesting *pNesting, size_t uOffset)
252{
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700253 pNesting->pCurrentMap = pNesting->pCurrent;
254 pNesting->pCurrentMap->uMapMode = 1;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700255 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700256 pNesting->pCurrentMap->uOffset = (uint32_t)uOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700257}
258
259inline static void
260DecodeNesting_Exit(QCBORDecodeNesting *pNesting)
261{
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700262 pNesting->pCurrentMap->uMapMode = 0;
263 pNesting->pCurrent = pNesting->pCurrentMap - 1; // TODO error check
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700264
265 DecodeNesting_DecrementCount(pNesting);
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700266
267 while(1) {
268 pNesting->pCurrentMap--;
269 if(pNesting->pCurrentMap->uMapMode) {
270 break;
271 }
272 if(pNesting->pCurrentMap == &(pNesting->pMapsAndArrays[0])) {
273 break;
274 }
275 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700276}
277
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800278// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800279inline static QCBORError
280DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700281{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700282 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800283
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800284 if(pItem->val.uCount == 0) {
285 // Nothing to do for empty definite lenth arrays. They are just are
286 // effectively the same as an item that is not a map or array
287 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530288 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800289 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800290
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800291 // Error out if arrays is too long to handle
292 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700293 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
294 goto Done;
295 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800296
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800297 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700298 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
299 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
300 goto Done;
301 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800302
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800303 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700304 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800305
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800306 // Record a few details for this nesting level
307 pNesting->pCurrent->uMajorType = pItem->uDataType;
308 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700309 pNesting->pCurrent->uSaveCount = pItem->val.uCount;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700310 pNesting->pCurrent->uMapMode = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800311
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700312Done:
313 return nReturn;;
314}
315
Laurence Lundbladeee851742020-01-08 08:37:05 -0800316inline static void
317DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700318{
319 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
320}
321
322
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700323static void DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
324{
325 *pSave = *pNesting;
326 pNesting->pCurrent = pNesting->pCurrentMap;
327
328 if(pNesting->pCurrent->uCount != UINT16_MAX) {
329 pNesting->pCurrent->uCount = pNesting->pCurrent->uSaveCount;
330 }
331}
332
333static void DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
334{
335 *pNesting = *pSave;
336}
337
338
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700339
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700340/*
341 This list of built-in tags. Only add tags here that are
342 clearly established and useful. Once a tag is added here
343 it can't be taken out as that would break backwards compatibility.
344 There are only 48 slots available forever.
345 */
346static const uint16_t spBuiltInTagMap[] = {
Laurence Lundblade59289e52019-12-30 13:44:37 -0800347 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
348 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
349 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
350 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
351 CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
352 CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700353 CBOR_TAG_COSE_ENCRYPTO,
354 CBOR_TAG_COSE_MAC0,
355 CBOR_TAG_COSE_SIGN1,
356 CBOR_TAG_ENC_AS_B64URL,
357 CBOR_TAG_ENC_AS_B64,
358 CBOR_TAG_ENC_AS_B16,
359 CBOR_TAG_CBOR,
360 CBOR_TAG_URI,
361 CBOR_TAG_B64URL,
362 CBOR_TAG_B64,
363 CBOR_TAG_REGEX,
364 CBOR_TAG_MIME,
365 CBOR_TAG_BIN_UUID,
366 CBOR_TAG_CWT,
367 CBOR_TAG_ENCRYPT,
368 CBOR_TAG_MAC,
369 CBOR_TAG_SIGN,
370 CBOR_TAG_GEO_COORD,
371 CBOR_TAG_CBOR_MAGIC
372};
373
374// This is used in a bit of cleverness in GetNext_TaggedItem() to
375// keep code size down and switch for the internal processing of
Laurence Lundblade59289e52019-12-30 13:44:37 -0800376// these types. This will break if the first six items in
377// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
378// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
379#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
380#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
381#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
382#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
383#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
384#define QCBOR_TAGFLAG_BIGFLOAT (0x01LL << CBOR_TAG_BIGFLOAT)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700385
Laurence Lundblade59289e52019-12-30 13:44:37 -0800386#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING |\
387 QCBOR_TAGFLAG_DATE_EPOCH |\
388 QCBOR_TAGFLAG_POS_BIGNUM |\
389 QCBOR_TAGFLAG_NEG_BIGNUM |\
390 QCBOR_TAGFLAG_DECIMAL_FRACTION |\
391 QCBOR_TAGFLAG_BIGFLOAT)
392
393#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
394 QCBOR_TAGFLAG_DATE_EPOCH |\
395 QCBOR_TAGFLAG_POS_BIGNUM |\
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700396 QCBOR_TAGFLAG_NEG_BIGNUM)
397
398#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
399#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
400#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
401
402static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
403{
404 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800405 /*
406 This is a cross-check to make sure the above array doesn't
407 accidentally get made too big. In normal conditions the above
408 test should optimize out as all the values are known at compile
409 time.
410 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700411 return -1;
412 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800413
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700414 if(uTag > UINT16_MAX) {
415 // This tag map works only on 16-bit tags
416 return -1;
417 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800418
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700419 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
420 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
421 return nTagBitIndex;
422 }
423 }
424 return -1; // Indicates no match
425}
426
427static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
428{
429 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
430 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
431 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
432 }
433 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800434
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700435 return -1; // Indicates no match
436}
437
438/*
439 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800440
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700441 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800442 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700443 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800444static QCBORError
445TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
446 uint64_t uTag,
447 uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700448{
449 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
450 if(nTagBitIndex >= 0) {
451 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
452 *puTagBitIndex = (uint8_t)nTagBitIndex;
453 return QCBOR_SUCCESS;
454 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800455
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700456 if(pCallerConfiguredTagMap) {
457 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
458 return QCBOR_ERR_TOO_MANY_TAGS;
459 }
460 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
461 if(nTagBitIndex >= 0) {
462 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
463
464 *puTagBitIndex = (uint8_t)nTagBitIndex;
465 return QCBOR_SUCCESS;
466 }
467 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800468
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700469 return QCBOR_ERR_BAD_OPT_TAG;
470}
471
472
473
Laurence Lundbladeee851742020-01-08 08:37:05 -0800474/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800475 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
476
477 The following four functions are pretty wrappers for invocation of
478 the string allocator supplied by the caller.
479
Laurence Lundbladeee851742020-01-08 08:37:05 -0800480 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800481
Laurence Lundbladeee851742020-01-08 08:37:05 -0800482static inline void
483StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800484{
485 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
486}
487
Laurence Lundbladeee851742020-01-08 08:37:05 -0800488// StringAllocator_Reallocate called with pMem NULL is
489// equal to StringAllocator_Allocate()
490static inline UsefulBuf
491StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
492 void *pMem,
493 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800494{
495 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
496}
497
Laurence Lundbladeee851742020-01-08 08:37:05 -0800498static inline UsefulBuf
499StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800500{
501 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
502}
503
Laurence Lundbladeee851742020-01-08 08:37:05 -0800504static inline void
505StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800506{
507 if(pMe->pfAllocator) {
508 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
509 }
510}
511
512
513
Laurence Lundbladeee851742020-01-08 08:37:05 -0800514/*===========================================================================
515 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700516
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800517 See qcbor/qcbor_decode.h for definition of the object
518 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800519 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700520/*
521 Public function, see header file
522 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800523void QCBORDecode_Init(QCBORDecodeContext *me,
524 UsefulBufC EncodedCBOR,
525 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700526{
527 memset(me, 0, sizeof(QCBORDecodeContext));
528 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800529 // Don't bother with error check on decode mode. If a bad value is
530 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700531 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700532 DecodeNesting_Init(&(me->nesting));
533}
534
535
536/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700537 Public function, see header file
538 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800539void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
540 QCBORStringAllocate pfAllocateFunction,
541 void *pAllocateContext,
542 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700543{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800544 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
545 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
546 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700547}
548
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800549
550/*
551 Public function, see header file
552 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800553void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
554 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700555{
556 me->pCallerConfiguredTagList = pTagList;
557}
558
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700559
560/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800561 This decodes the fundamental part of a CBOR data item, the type and
562 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800563
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700564 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800565
Laurence Lundbladeee851742020-01-08 08:37:05 -0800566 This does the network->host byte order conversion. The conversion
567 here also results in the conversion for floats in addition to that
568 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800569
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700570 This returns:
571 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800572
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800573 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800574 tags and floats and length for strings and arrays
575
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800576 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800577 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800578
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800579 The int type is preferred to uint8_t for some variables as this
580 avoids integer promotions, can reduce code size and makes
581 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700582 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800583inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
584 int *pnMajorType,
585 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800586 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700587{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700588 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800589
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700590 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800591 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800592
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700593 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800594 const int nTmpMajorType = nInitialByte >> 5;
595 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800596
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800597 // Where the number or argument accumulates
598 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800599
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800600 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800601 // Need to get 1,2,4 or 8 additional argument bytes Map
602 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800603 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800604
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800605 // Loop getting all the bytes in the argument
606 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800607 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800608 // This shift and add gives the endian conversion
609 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
610 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800611 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800612 // The reserved and thus-far unused additional info values
613 nReturn = QCBOR_ERR_UNSUPPORTED;
614 goto Done;
615 } else {
616 // Less than 24, additional info is argument or 31, an indefinite length
617 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800618 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700619 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800620
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700621 if(UsefulInputBuf_GetError(pUInBuf)) {
622 nReturn = QCBOR_ERR_HIT_END;
623 goto Done;
624 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800625
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700626 // All successful if we got here.
627 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800628 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800629 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800630 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800631
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700632Done:
633 return nReturn;
634}
635
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800636
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700637/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800638 CBOR doesn't explicitly specify two's compliment for integers but all
639 CPUs use it these days and the test vectors in the RFC are so. All
640 integers in the CBOR structure are positive and the major type
641 indicates positive or negative. CBOR can express positive integers
642 up to 2^x - 1 where x is the number of bits and negative integers
643 down to 2^x. Note that negative numbers can be one more away from
644 zero than positive. Stdint, as far as I can tell, uses two's
645 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800646
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700647 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800648 used carefully here, and in particular why it isn't used in the interface.
649 Also see
650 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
651
652 Int is used for values that need less than 16-bits and would be subject
653 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700654 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800655inline static QCBORError
656DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700657{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700658 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800659
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700660 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
661 if (uNumber <= INT64_MAX) {
662 pDecodedItem->val.int64 = (int64_t)uNumber;
663 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800664
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700665 } else {
666 pDecodedItem->val.uint64 = uNumber;
667 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800668
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700669 }
670 } else {
671 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800672 // CBOR's representation of negative numbers lines up with the
673 // two-compliment representation. A negative integer has one
674 // more in range than a positive integer. INT64_MIN is
675 // equal to (-INT64_MAX) - 1.
676 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700677 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800678
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700679 } else {
680 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000681 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700682 nReturn = QCBOR_ERR_INT_OVERFLOW;
683 }
684 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800685
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700686 return nReturn;
687}
688
689// Make sure #define value line up as DecodeSimple counts on this.
690#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
691#error QCBOR_TYPE_FALSE macro value wrong
692#endif
693
694#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
695#error QCBOR_TYPE_TRUE macro value wrong
696#endif
697
698#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
699#error QCBOR_TYPE_NULL macro value wrong
700#endif
701
702#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
703#error QCBOR_TYPE_UNDEF macro value wrong
704#endif
705
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700706#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
707#error QCBOR_TYPE_BREAK macro value wrong
708#endif
709
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700710#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
711#error QCBOR_TYPE_DOUBLE macro value wrong
712#endif
713
714#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
715#error QCBOR_TYPE_FLOAT macro value wrong
716#endif
717
718/*
719 Decode true, false, floats, break...
720 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800721inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800722DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700723{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700724 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800725
Laurence Lundbladeee851742020-01-08 08:37:05 -0800726 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800727 // above make sure uAdditionalInfo values line up with uDataType values.
728 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
729 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800730
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800731 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800732 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
733 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800734
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700735 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700736 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
737 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700738 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700739 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700740 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
741 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700742 break;
743 case DOUBLE_PREC_FLOAT:
744 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700745 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700746 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800747
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700748 case CBOR_SIMPLEV_FALSE: // 20
749 case CBOR_SIMPLEV_TRUE: // 21
750 case CBOR_SIMPLEV_NULL: // 22
751 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700752 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700753 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800754
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700755 case CBOR_SIMPLEV_ONEBYTE: // 24
756 if(uNumber <= CBOR_SIMPLE_BREAK) {
757 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700758 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700759 goto Done;
760 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800761 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700762 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800763
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700764 default: // 0-19
765 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800766 /*
767 DecodeTypeAndNumber will make uNumber equal to
768 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
769 safe because the 2, 4 and 8 byte lengths of uNumber are in
770 the double/float cases above
771 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700772 pDecodedItem->val.uSimple = (uint8_t)uNumber;
773 break;
774 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800775
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700776Done:
777 return nReturn;
778}
779
780
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700781/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530782 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700783 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800784inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
785 int nMajorType,
786 uint64_t uStrLen,
787 UsefulInputBuf *pUInBuf,
788 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700789{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700790 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800791
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800792 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
793 // This check makes the casts to size_t below safe.
794
795 // 4 bytes less than the largest sizeof() so this can be tested by
796 // putting a SIZE_MAX length in the CBOR test input (no one will
797 // care the limit on strings is 4 bytes shorter).
798 if(uStrLen > SIZE_MAX-4) {
799 nReturn = QCBOR_ERR_STRING_TOO_LONG;
800 goto Done;
801 }
802
803 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530804 if(UsefulBuf_IsNULLC(Bytes)) {
805 // Failed to get the bytes for this string item
806 nReturn = QCBOR_ERR_HIT_END;
807 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700808 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530809
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800810 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530811 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800812 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530813 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700814 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530815 goto Done;
816 }
817 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800818 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530819 } else {
820 // Normal case with no string allocator
821 pDecodedItem->val.string = Bytes;
822 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800823 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800824 // Cast because ternary operator causes promotion to integer
825 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
826 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800827
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530828Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700829 return nReturn;
830}
831
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700832
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800833
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700834
835
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700836
837
Laurence Lundbladeee851742020-01-08 08:37:05 -0800838// Make sure the constants align as this is assumed by
839// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700840#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
841#error QCBOR_TYPE_ARRAY value not lined up with major type
842#endif
843#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
844#error QCBOR_TYPE_MAP value not lined up with major type
845#endif
846
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700847/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800848 This gets a single data item and decodes it including preceding
849 optional tagging. This does not deal with arrays and maps and nesting
850 except to decode the data item introducing them. Arrays and maps are
851 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800852
Laurence Lundbladeee851742020-01-08 08:37:05 -0800853 Errors detected here include: an array that is too long to decode,
854 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700855 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800856static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
857 QCBORItem *pDecodedItem,
858 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700859{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700860 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800861
Laurence Lundbladeee851742020-01-08 08:37:05 -0800862 /*
863 Get the major type and the number. Number could be length of more
864 bytes or the value depending on the major type nAdditionalInfo is
865 an encoding of the length of the uNumber and is needed to decode
866 floats and doubles
867 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800868 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700869 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800870 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800871
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700872 memset(pDecodedItem, 0, sizeof(QCBORItem));
873
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800874 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800875
Laurence Lundbladeee851742020-01-08 08:37:05 -0800876 // Error out here if we got into trouble on the type and number. The
877 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700878 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700879 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700880 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800881
Laurence Lundbladeee851742020-01-08 08:37:05 -0800882 // At this point the major type and the value are valid. We've got
883 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800884 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700885 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
886 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800887 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700888 nReturn = QCBOR_ERR_BAD_INT;
889 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800890 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700891 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700892 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800893
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700894 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
895 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800896 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
897 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
898 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
899 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530900 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700901 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800902 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700903 }
904 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800905
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700906 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
907 case CBOR_MAJOR_TYPE_MAP: // Major type 5
908 // Record the number of items in the array or map
909 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
910 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
911 goto Done;
912 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800913 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530914 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700915 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800916 // type conversion OK because of check above
917 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700918 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800919 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800920 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
921 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700922 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800923
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700924 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800925 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700926 nReturn = QCBOR_ERR_BAD_INT;
927 } else {
928 pDecodedItem->val.uTagV = uNumber;
929 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
930 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700931 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800932
Laurence Lundbladeee851742020-01-08 08:37:05 -0800933 case CBOR_MAJOR_TYPE_SIMPLE:
934 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800935 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700936 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800937
Laurence Lundbladeee851742020-01-08 08:37:05 -0800938 default:
939 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700940 nReturn = QCBOR_ERR_UNSUPPORTED;
941 break;
942 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800943
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700944Done:
945 return nReturn;
946}
947
948
949
950/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800951 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800952 individual chunk items together into one QCBORItem using the string
953 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800954
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530955 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700956 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800957static inline QCBORError
958GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700959{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700960 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700961
962 // Get pointer to string allocator. First use is to pass it to
963 // GetNext_Item() when option is set to allocate for *every* string.
964 // Second use here is to allocate space to coallese indefinite
965 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800966 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
967 &(me->StringAllocator) :
968 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800969
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700970 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800971 nReturn = GetNext_Item(&(me->InBuf),
972 pDecodedItem,
973 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700974 if(nReturn) {
975 goto Done;
976 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800977
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700978 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530979 // code in this function from here down can be eliminated. Run tests, except
980 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800981
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800982 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700983 const uint8_t uStringType = pDecodedItem->uDataType;
984 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700985 goto Done; // no need to do any work here on non-string types
986 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800987
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800988 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530989 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800990 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700991 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800992
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530993 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800994 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700995 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
996 goto Done;
997 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800998
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700999 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001000 UsefulBufC FullString = NULLUsefulBufC;
1001
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001003 // Get item for next chunk
1004 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001005 // NULL string allocator passed here. Do not need to allocate
1006 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001007 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001008 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001009 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001010 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001011
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301012 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001013 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001014 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001015 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301016 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001017 break;
1018 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001019
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001020 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301021 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001022 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001023 if(StringChunkItem.uDataType != uStringType ||
1024 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001025 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001026 break;
1027 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001028
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301029 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001030 // The first time throurgh FullString.ptr is NULL and this is
1031 // equivalent to StringAllocator_Allocate()
1032 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1033 UNCONST_POINTER(FullString.ptr),
1034 FullString.len + StringChunkItem.val.string.len);
1035
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001036 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301037 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001038 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001039 break;
1040 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001041
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001042 // Copy new string chunk at the end of string so far.
1043 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001044 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001045
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001046 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1047 // Getting the item failed, clean up the allocated memory
1048 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001049 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001050
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001051Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001052 return nReturn;
1053}
1054
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001055
1056/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001057 Gets all optional tag data items preceding a data item that is not an
1058 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001059 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001060static QCBORError
1061GetNext_TaggedItem(QCBORDecodeContext *me,
1062 QCBORItem *pDecodedItem,
1063 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001064{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001065 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +07001066 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001067 uint64_t uTagBits = 0;
1068 if(pTags) {
1069 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001070 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001071
Laurence Lundblade59289e52019-12-30 13:44:37 -08001072 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001073 for(;;) {
1074 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001075 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001076 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001077 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001078
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001079 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1080 // Successful exit from loop; maybe got some tags, maybe not
1081 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001082 break;
1083 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001084
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001085 uint8_t uTagBitIndex;
1086 // Tag was mapped, tag was not mapped, error with tag list
1087 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001088
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001089 case QCBOR_SUCCESS:
1090 // Successfully mapped the tag
1091 uTagBits |= 0x01ULL << uTagBitIndex;
1092 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001093
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001094 case QCBOR_ERR_BAD_OPT_TAG:
1095 // Tag is not recognized. Do nothing
1096 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001097
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001098 default:
1099 // Error Condition
1100 goto Done;
1101 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001102
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001103 if(pTags) {
1104 // Caller wants all tags recorded in the provided buffer
1105 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1106 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
1107 goto Done;
1108 }
1109 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
1110 pTags->uNumUsed++;
1111 }
1112 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001113
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001114Done:
1115 return nReturn;
1116}
1117
1118
1119/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001120 This layer takes care of map entries. It combines the label and data
1121 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001122 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001123static inline QCBORError
1124GetNext_MapEntry(QCBORDecodeContext *me,
1125 QCBORItem *pDecodedItem,
1126 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001127{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001128 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +07001129 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001130 if(nReturn)
1131 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001132
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001133 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001134 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001135 goto Done;
1136 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001137
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001138 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1139 // In a map and caller wants maps decoded, not treated as arrays
1140
1141 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1142 // If in a map and the right decoding mode, get the label
1143
Laurence Lundbladeee851742020-01-08 08:37:05 -08001144 // Save label in pDecodedItem and get the next which will
1145 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001146 QCBORItem LabelItem = *pDecodedItem;
1147 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1148 if(nReturn)
1149 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001150
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301151 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001152
1153 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1154 // strings are always good labels
1155 pDecodedItem->label.string = LabelItem.val.string;
1156 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1157 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001158 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001159 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1160 goto Done;
1161 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1162 pDecodedItem->label.int64 = LabelItem.val.int64;
1163 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1164 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1165 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1166 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1167 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1168 pDecodedItem->label.string = LabelItem.val.string;
1169 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1170 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1171 } else {
1172 // label is not an int or a string. It is an arrray
1173 // or a float or such and this implementation doesn't handle that.
1174 // Also, tags on labels are ignored.
1175 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1176 goto Done;
1177 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001178 }
1179 } else {
1180 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001181 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1182 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1183 goto Done;
1184 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001185 // Decoding a map as an array
1186 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001187 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1188 // Cast is needed because of integer promotion
1189 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001190 }
1191 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001192
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001193Done:
1194 return nReturn;
1195}
1196
1197
1198/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001199 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001200 TODO: correct this comment
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001201 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001202QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
1203 QCBORItem *pDecodedItem,
1204 QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001205{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001206 // Stack ptr/int: 2, QCBORItem : 64
1207
Laurence Lundblade30816f22018-11-10 13:40:22 +07001208 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001209
Laurence Lundblade937ea812020-05-08 11:38:23 -07001210 /* For a pre-order traversal a non-error end occurs when there
1211 are no more bytes to consume and the nesting level is at the top.
1212 If it's not at the top, then the CBOR is not well formed. This error
1213 is caught elsewhere.
1214
1215 This handles the end of CBOR sequences as well as non-sequences. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001216 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001217 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1218 goto Done;
1219 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001220
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001221 /* It is also an end of the input when in map mode and the cursor
Laurence Lundblade937ea812020-05-08 11:38:23 -07001222 is at the end of the map */
1223
1224
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001225 // This is to handle map and array mode
Laurence Lundblade937ea812020-05-08 11:38:23 -07001226 if(DecodeNesting_AtEnd(&(me->nesting))) {
1227// if(UsefulInputBuf_Tell(&(me->InBuf)) != 0 && DecodeNesting_AtEnd(&(me->nesting))) {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001228 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1229 goto Done;
1230 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001231
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001232 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001233 if(nReturn) {
1234 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001235 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301236
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001237 // Breaks ending arrays/maps are always processed at the end of this function.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301238 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301239 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301240 nReturn = QCBOR_ERR_BAD_BREAK;
1241 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301242 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001243
Laurence Lundblade6de37062018-10-15 12:22:42 +05301244 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301245 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301246 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001247
Laurence Lundblade6de37062018-10-15 12:22:42 +05301248 // Process the item just received for descent or decrement, and
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001249 // ascend if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001250 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001251 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001252 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001253 // Maps and arrays do count in as items in the map/array that encloses
1254 // them so a decrement needs to be done for them too, but that is done
1255 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001256 // are opened with the exception of an empty map or array.
1257 if(pDecodedItem->val.uCount == 0) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001258 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001259 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001260 } else {
1261 // Decrement the count of items in the enclosing map/array
1262 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301263 // triggers a decrement in the map/array above that and
1264 // an ascend in nesting level.
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001265 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001266 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301267 if(nReturn) {
1268 goto Done;
1269 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001270
Laurence Lundblade6de37062018-10-15 12:22:42 +05301271 // For indefinite length maps/arrays, looking at any and
1272 // all breaks that might terminate them. The equivalent
1273 // for definite length maps/arrays happens in
1274 // DecodeNesting_DecrementCount().
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001275 if(!DecodeNesting_IsAtTop(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301276 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1277 // Peek forward one item to see if it is a break.
1278 QCBORItem Peek;
1279 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1280 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1281 if(nReturn) {
1282 goto Done;
1283 }
1284 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1285 // It is not a break, rewind so it can be processed normally.
1286 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1287 break;
1288 }
1289 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301290 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301291 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1292 if(nReturn) {
1293 // break occured outside of an indefinite length array/map
1294 goto Done;
1295 }
1296 }
1297 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001298
Laurence Lundblade6de37062018-10-15 12:22:42 +05301299 // Tell the caller what level is next. This tells them what maps/arrays
1300 // were closed out and makes it possible for them to reconstruct
1301 // the tree with just the information returned by GetNext
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07001302 // TODO: pull this into DecodeNesting_GetLevel
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001303 if(me->nesting.pCurrent->uMapMode && me->nesting.pCurrent->uCount == 0) {
1304 // At end of a map / array in map mode, so next nest is 0 to
1305 // indicate this end.
1306 pDecodedItem->uNextNestLevel = 0;
1307 } else {
1308 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
1309 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001310
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001311Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001312 if(nReturn != QCBOR_SUCCESS) {
1313 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1314 memset(pDecodedItem, 0, sizeof(QCBORItem));
1315 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001316 return nReturn;
1317}
1318
1319
Laurence Lundblade59289e52019-12-30 13:44:37 -08001320/*
1321 Mostly just assign the right data type for the date string.
1322 */
1323inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1324{
1325 // Stack Use: UsefulBuf 1 16
1326 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1327 return QCBOR_ERR_BAD_OPT_TAG;
1328 }
1329
1330 const UsefulBufC Temp = pDecodedItem->val.string;
1331 pDecodedItem->val.dateString = Temp;
1332 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1333 return QCBOR_SUCCESS;
1334}
1335
1336
1337/*
1338 Mostly just assign the right data type for the bignum.
1339 */
1340inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1341{
1342 // Stack Use: UsefulBuf 1 -- 16
1343 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1344 return QCBOR_ERR_BAD_OPT_TAG;
1345 }
1346 const UsefulBufC Temp = pDecodedItem->val.string;
1347 pDecodedItem->val.bigNum = Temp;
Laurence Lundbladeee851742020-01-08 08:37:05 -08001348 const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001349 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1350 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001351 return QCBOR_SUCCESS;
1352}
1353
1354
1355/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001356 The epoch formatted date. Turns lots of different forms of encoding
1357 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001358 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001359static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001360{
1361 // Stack usage: 1
1362 QCBORError nReturn = QCBOR_SUCCESS;
1363
1364 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1365
1366 switch (pDecodedItem->uDataType) {
1367
1368 case QCBOR_TYPE_INT64:
1369 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1370 break;
1371
1372 case QCBOR_TYPE_UINT64:
1373 if(pDecodedItem->val.uint64 > INT64_MAX) {
1374 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1375 goto Done;
1376 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001377 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001378 break;
1379
1380 case QCBOR_TYPE_DOUBLE:
1381 {
1382 // This comparison needs to be done as a float before
1383 // conversion to an int64_t to be able to detect doubles
1384 // that are too large to fit into an int64_t. A double
1385 // has 52 bits of preceision. An int64_t has 63. Casting
1386 // INT64_MAX to a double actually causes a round up which
1387 // is bad and wrong for the comparison because it will
1388 // allow conversion of doubles that can't fit into a
1389 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1390 // the cutoff point as if that rounds up in conversion to
1391 // double it will still be less than INT64_MAX. 0x7ff is
1392 // picked because it has 11 bits set.
1393 //
1394 // INT64_MAX seconds is on the order of 10 billion years,
1395 // and the earth is less than 5 billion years old, so for
1396 // most uses this conversion error won't occur even though
1397 // doubles can go much larger.
1398 //
1399 // Without the 0x7ff there is a ~30 minute range of time
1400 // values 10 billion years in the past and in the future
1401 // where this this code would go wrong.
1402 const double d = pDecodedItem->val.dfnum;
1403 if(d > (double)(INT64_MAX - 0x7ff)) {
1404 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1405 goto Done;
1406 }
1407 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1408 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1409 }
1410 break;
1411
1412 default:
1413 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1414 goto Done;
1415 }
1416 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1417
1418Done:
1419 return nReturn;
1420}
1421
1422
1423#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1424/*
1425 Decode decimal fractions and big floats.
1426
1427 When called pDecodedItem must be the array that is tagged as a big
1428 float or decimal fraction, the array that has the two members, the
1429 exponent and mantissa.
1430
1431 This will fetch and decode the exponent and mantissa and put the
1432 result back into pDecodedItem.
1433 */
1434inline static QCBORError
1435QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1436{
1437 QCBORError nReturn;
1438
1439 // --- Make sure it is an array; track nesting level of members ---
1440 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1441 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1442 goto Done;
1443 }
1444
1445 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001446 // definite length arrays, but not for indefnite. Instead remember
1447 // the nesting level the two integers must be at, which is one
1448 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001449 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1450
1451 // --- Is it a decimal fraction or a bigfloat? ---
1452 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1453 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1454
1455 // --- Get the exponent ---
1456 QCBORItem exponentItem;
1457 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
1458 if(nReturn != QCBOR_SUCCESS) {
1459 goto Done;
1460 }
1461 if(exponentItem.uNestingLevel != nNestLevel) {
1462 // Array is empty or a map/array encountered when expecting an int
1463 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1464 goto Done;
1465 }
1466 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1467 // Data arriving as an unsigned int < INT64_MAX has been converted
1468 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1469 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1470 // will be too large for this to handle and thus an error that will
1471 // get handled in the next else.
1472 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1473 } else {
1474 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1475 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1476 goto Done;
1477 }
1478
1479 // --- Get the mantissa ---
1480 QCBORItem mantissaItem;
1481 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1482 if(nReturn != QCBOR_SUCCESS) {
1483 goto Done;
1484 }
1485 if(mantissaItem.uNestingLevel != nNestLevel) {
1486 // Mantissa missing or map/array encountered when expecting number
1487 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1488 goto Done;
1489 }
1490 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1491 // Data arriving as an unsigned int < INT64_MAX has been converted
1492 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1493 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1494 // will be too large for this to handle and thus an error that
1495 // will get handled in an else below.
1496 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1497 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1498 // Got a good big num mantissa
1499 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1500 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001501 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1502 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1503 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001504 } else {
1505 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1506 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1507 goto Done;
1508 }
1509
1510 // --- Check that array only has the two numbers ---
1511 if(mantissaItem.uNextNestLevel == nNestLevel) {
1512 // Extra items in the decimal fraction / big num
1513 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1514 goto Done;
1515 }
1516
1517Done:
1518
1519 return nReturn;
1520}
1521#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1522
1523
1524/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001525 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001526 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001527QCBORError
1528QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1529 QCBORItem *pDecodedItem,
1530 QCBORTagListOut *pTags)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001531{
1532 QCBORError nReturn;
1533
1534 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
1535 if(nReturn != QCBOR_SUCCESS) {
1536 goto Done;
1537 }
1538
1539#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1540#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
1541#else
1542#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
1543#endif
1544
1545 // Only pay attention to tags this code knows how to decode.
1546 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
1547 case 0:
1548 // No tags at all or none we know about. Nothing to do.
1549 // This is the pass-through path of this function
1550 // that will mostly be taken when decoding any item.
1551 break;
1552
1553 case QCBOR_TAGFLAG_DATE_STRING:
1554 nReturn = DecodeDateString(pDecodedItem);
1555 break;
1556
1557 case QCBOR_TAGFLAG_DATE_EPOCH:
1558 nReturn = DecodeDateEpoch(pDecodedItem);
1559 break;
1560
1561 case QCBOR_TAGFLAG_POS_BIGNUM:
1562 case QCBOR_TAGFLAG_NEG_BIGNUM:
1563 nReturn = DecodeBigNum(pDecodedItem);
1564 break;
1565
1566#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1567 case QCBOR_TAGFLAG_DECIMAL_FRACTION:
1568 case QCBOR_TAGFLAG_BIGFLOAT:
1569 // For aggregate tagged types, what goes into pTags is only collected
1570 // from the surrounding data item, not the contents, so pTags is not
1571 // passed on here.
1572
1573 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1574 break;
1575#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1576
1577 default:
1578 // Encountering some mixed-up CBOR like something that
1579 // is tagged as both a string and integer date.
1580 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1581 }
1582
1583Done:
1584 if(nReturn != QCBOR_SUCCESS) {
1585 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1586 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1587 }
1588 return nReturn;
1589}
1590
1591
1592/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001593 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001594 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001595QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001596{
1597 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1598}
1599
1600
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001601/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301602 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301603 next one down. If a layer has no work to do for a particular item
1604 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001605
Laurence Lundblade59289e52019-12-30 13:44:37 -08001606 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1607 tagged data items, turning them into the local C representation.
1608 For the most simple it is just associating a QCBOR_TYPE with the data. For
1609 the complex ones that an aggregate of data items, there is some further
1610 decoding and a little bit of recursion.
1611
1612 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301613 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301614 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001615 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001616
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301617 - GetNext_MapEntry -- This handles the combining of two
1618 items, the label and the data, that make up a map entry.
1619 It only does work on maps. It combines the label and data
1620 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001621
Laurence Lundblade59289e52019-12-30 13:44:37 -08001622 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1623 tags into bit flags associated with the data item. No actual decoding
1624 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001625
Laurence Lundblade59289e52019-12-30 13:44:37 -08001626 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301627 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301628 string allocater to create contiguous space for the item. It
1629 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001630
Laurence Lundblade59289e52019-12-30 13:44:37 -08001631 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1632 atomic data item has a "major type", an integer "argument" and optionally
1633 some content. For text and byte strings, the content is the bytes
1634 that make up the string. These are the smallest data items that are
1635 considered to be well-formed. The content may also be other data items in
1636 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001637
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001638 Roughly this takes 300 bytes of stack for vars. Need to
1639 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001640
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301641 */
1642
1643
1644/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001645 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001646 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001647int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1648 const QCBORItem *pItem,
1649 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001650{
1651 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001652
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001653 uint8_t uTagBitIndex;
1654 // Do not care about errors in pCallerConfiguredTagMap here. They are
1655 // caught during GetNext() before this is called.
1656 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1657 return 0;
1658 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001659
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001660 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1661 return (uTagBit & pItem->uTagBits) != 0;
1662}
1663
1664
1665/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001666 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001667 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001668QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001669{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001670 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001671
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001672 // Error out if all the maps/arrays are not closed out
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001673 if(!DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001674 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1675 goto Done;
1676 }
1677
1678 // Error out if not all the bytes are consumed
1679 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1680 nReturn = QCBOR_ERR_EXTRA_BYTES;
1681 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001682
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001683Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301684 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001685 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001686 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001687
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001688 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001689}
1690
1691
1692
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001693/*
1694
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001695Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001696
Laurence Lundbladeee851742020-01-08 08:37:05 -08001697 - Hit end of input before it was expected while decoding type and
1698 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001699
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001700 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001701
Laurence Lundbladeee851742020-01-08 08:37:05 -08001702 - Hit end of input while decoding a text or byte string
1703 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001704
Laurence Lundbladeee851742020-01-08 08:37:05 -08001705 - Encountered conflicting tags -- e.g., an item is tagged both a date
1706 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001707
Laurence Lundbladeee851742020-01-08 08:37:05 -08001708 - Encontered an array or mapp that has too many items
1709 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001710
Laurence Lundbladeee851742020-01-08 08:37:05 -08001711 - Encountered array/map nesting that is too deep
1712 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001713
Laurence Lundbladeee851742020-01-08 08:37:05 -08001714 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1715 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001716
Laurence Lundbladeee851742020-01-08 08:37:05 -08001717 - The type of a map label is not a string or int
1718 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001719
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001720 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001721
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001722 */
1723
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001724
1725
Laurence Lundbladef6531662018-12-04 10:42:22 +09001726
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001727/* ===========================================================================
1728 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001729
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001730 This implements a simple sting allocator for indefinite length
1731 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1732 implements the function type QCBORStringAllocate and allows easy
1733 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001734
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001735 This particular allocator is built-in for convenience. The caller
1736 can implement their own. All of this following code will get
1737 dead-stripped if QCBORDecode_SetMemPool() is not called.
1738
1739 This is a very primitive memory allocator. It does not track
1740 individual allocations, only a high-water mark. A free or
1741 reallocation must be of the last chunk allocated.
1742
1743 The size of the pool and offset to free memory are packed into the
1744 first 8 bytes of the memory pool so we don't have to keep them in
1745 the decode context. Since the address of the pool may not be
1746 aligned, they have to be packed and unpacked as if they were
1747 serialized data of the wire or such.
1748
1749 The sizes packed in are uint32_t to be the same on all CPU types
1750 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001751 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001752
1753
Laurence Lundbladeee851742020-01-08 08:37:05 -08001754static inline int
1755MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001756{
1757 // Use of UsefulInputBuf is overkill, but it is convenient.
1758 UsefulInputBuf UIB;
1759
Laurence Lundbladeee851742020-01-08 08:37:05 -08001760 // Just assume the size here. It was checked during SetUp so
1761 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001762 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1763 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1764 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1765 return UsefulInputBuf_GetError(&UIB);
1766}
1767
1768
Laurence Lundbladeee851742020-01-08 08:37:05 -08001769static inline int
1770MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001771{
1772 // Use of UsefulOutBuf is overkill, but convenient. The
1773 // length check performed here is useful.
1774 UsefulOutBuf UOB;
1775
1776 UsefulOutBuf_Init(&UOB, Pool);
1777 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1778 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1779 return UsefulOutBuf_GetError(&UOB);
1780}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001781
1782
1783/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001784 Internal function for an allocation, reallocation free and destuct.
1785
1786 Having only one function rather than one each per mode saves space in
1787 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001788
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001789 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1790 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001791static UsefulBuf
1792MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001793{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001794 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001795
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001796 uint32_t uPoolSize;
1797 uint32_t uFreeOffset;
1798
1799 if(uNewSize > UINT32_MAX) {
1800 // This allocator is only good up to 4GB. This check should
1801 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1802 goto Done;
1803 }
1804 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1805
1806 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1807 goto Done;
1808 }
1809
1810 if(uNewSize) {
1811 if(pMem) {
1812 // REALLOCATION MODE
1813 // Calculate pointer to the end of the memory pool. It is
1814 // assumed that pPool + uPoolSize won't wrap around by
1815 // assuming the caller won't pass a pool buffer in that is
1816 // not in legitimate memory space.
1817 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1818
1819 // Check that the pointer for reallocation is in the range of the
1820 // pool. This also makes sure that pointer math further down
1821 // doesn't wrap under or over.
1822 if(pMem >= pPool && pMem < pPoolEnd) {
1823 // Offset to start of chunk for reallocation. This won't
1824 // wrap under because of check that pMem >= pPool. Cast
1825 // is safe because the pool is always less than UINT32_MAX
1826 // because of check in QCBORDecode_SetMemPool().
1827 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1828
1829 // Check to see if the allocation will fit. uPoolSize -
1830 // uMemOffset will not wrap under because of check that
1831 // pMem is in the range of the uPoolSize by check above.
1832 if(uNewSize <= uPoolSize - uMemOffset) {
1833 ReturnValue.ptr = pMem;
1834 ReturnValue.len = uNewSize;
1835
1836 // Addition won't wrap around over because uNewSize was
1837 // checked to be sure it is less than the pool size.
1838 uFreeOffset = uMemOffset + uNewSize32;
1839 }
1840 }
1841 } else {
1842 // ALLOCATION MODE
1843 // uPoolSize - uFreeOffset will not underflow because this
1844 // pool implementation makes sure uFreeOffset is always
1845 // smaller than uPoolSize through this check here and
1846 // reallocation case.
1847 if(uNewSize <= uPoolSize - uFreeOffset) {
1848 ReturnValue.len = uNewSize;
1849 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001850 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001851 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001852 }
1853 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001854 if(pMem) {
1855 // FREE MODE
1856 // Cast is safe because of limit on pool size in
1857 // QCBORDecode_SetMemPool()
1858 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1859 } else {
1860 // DESTRUCT MODE
1861 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001862 }
1863 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001864
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001865 UsefulBuf Pool = {pPool, uPoolSize};
1866 MemPool_Pack(Pool, uFreeOffset);
1867
1868Done:
1869 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001870}
1871
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001872
Laurence Lundbladef6531662018-12-04 10:42:22 +09001873/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001874 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09001875 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001876QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1877 UsefulBuf Pool,
1878 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001879{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001880 // The pool size and free mem offset are packed into the beginning
1881 // of the pool memory. This compile time check make sure the
1882 // constant in the header is correct. This check should optimize
1883 // down to nothing.
1884 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001885 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001886 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001887
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001888 // The pool size and free offset packed in to the beginning of pool
1889 // memory are only 32-bits. This check will optimize out on 32-bit
1890 // machines.
1891 if(Pool.len > UINT32_MAX) {
1892 return QCBOR_ERR_BUFFER_TOO_LARGE;
1893 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001894
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001895 // This checks that the pool buffer given is big enough.
1896 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1897 return QCBOR_ERR_BUFFER_TOO_SMALL;
1898 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001899
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001900 pMe->StringAllocator.pfAllocator = MemPool_Function;
1901 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1902 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001903
Laurence Lundblade30816f22018-11-10 13:40:22 +07001904 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001905}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001906
Laurence Lundblade1341c592020-04-11 14:19:05 -07001907#include <stdio.h>
1908void printdecode(QCBORDecodeContext *pMe, const char *szName)
1909{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001910 printf("---%s--%d--%d--\nLevel Count Type Offset SaveCount MapMode\n",
1911 szName,
1912 (uint32_t)pMe->InBuf.cursor,
1913 (uint32_t)pMe->InBuf.UB.len);
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001914 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001915 if(&(pMe->nesting.pMapsAndArrays[i]) > pMe->nesting.pCurrent) {
1916 break;
1917 }
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001918 printf("%2s %2d %5d %s %6u %2d %d\n",
1919 pMe->nesting.pCurrentMap == &(pMe->nesting.pMapsAndArrays[i]) ? "->": " ",
Laurence Lundblade1341c592020-04-11 14:19:05 -07001920 i,
1921 pMe->nesting.pMapsAndArrays[i].uCount,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001922 pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_MAP ? " map" :
1923 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_ARRAY ? "array" :
1924 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_NONE ? " none" : "?????")),
Laurence Lundblade1341c592020-04-11 14:19:05 -07001925 pMe->nesting.pMapsAndArrays[i].uOffset,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001926 pMe->nesting.pMapsAndArrays[i].uSaveCount,
1927 pMe->nesting.pMapsAndArrays[i].uMapMode
Laurence Lundblade1341c592020-04-11 14:19:05 -07001928 );
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001929
Laurence Lundblade1341c592020-04-11 14:19:05 -07001930 }
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001931 printf("\n");
Laurence Lundblade1341c592020-04-11 14:19:05 -07001932}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001933
1934
1935/*
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001936 *
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001937 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001938static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001939ConsumeItem(QCBORDecodeContext *pMe,
1940 const QCBORItem *pItemToConsume,
1941 uint_fast8_t *puNextNestLevel)
1942{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001943 QCBORError nReturn;
1944 QCBORItem Item;
1945
1946 printdecode(pMe, "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001947
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001948 if(IsMapOrArray(pItemToConsume->uDataType)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001949 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001950
Laurence Lundblade1341c592020-04-11 14:19:05 -07001951 /* This works for definite and indefinite length
1952 * maps and arrays by using the nesting level
1953 */
1954 do {
1955 nReturn = QCBORDecode_GetNext(pMe, &Item);
1956 if(nReturn != QCBOR_SUCCESS) {
1957 goto Done;
1958 }
1959 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001960
Laurence Lundblade1341c592020-04-11 14:19:05 -07001961 if(puNextNestLevel != NULL) {
1962 *puNextNestLevel = Item.uNextNestLevel;
1963 }
1964 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001965
Laurence Lundblade1341c592020-04-11 14:19:05 -07001966 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001967 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07001968 if(puNextNestLevel != NULL) {
1969 /* Just pass the nesting level through */
1970 *puNextNestLevel = pItemToConsume->uNextNestLevel;
1971 }
1972 nReturn = QCBOR_SUCCESS;
1973 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001974
1975Done:
1976 return nReturn;
1977}
1978
1979
Laurence Lundblade1341c592020-04-11 14:19:05 -07001980/* Return true if the labels in Item1 and Item2 are the same.
1981 Works only for integer and string labels. Returns false
1982 for any other type. */
1983static inline bool
1984MatchLabel(QCBORItem Item1, QCBORItem Item2)
1985{
1986 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
1987 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
1988 return true;
1989 }
1990 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001991 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001992 return true;
1993 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001994 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07001995 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
1996 return true;
1997 }
1998 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
1999 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2000 return true;
2001 }
2002 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002003
Laurence Lundblade1341c592020-04-11 14:19:05 -07002004 /* Other label types are never matched */
2005 return false;
2006}
2007
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002008static inline bool
2009MatchType(QCBORItem Item1, QCBORItem Item2)
2010{
2011 if(Item1.uDataType == Item2.uDataType) {
2012 return true;
2013 } else if(Item1.uLabelType == QCBOR_TYPE_ANY) {
2014 return true;
2015 } else if(Item2.uLabelType == QCBOR_TYPE_ANY) {
2016 return true;
2017 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002018 return false;
2019}
2020
2021
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002022/*
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002023 On input pItemArray contains a list of labels and data types
2024 of items to be found.
2025
2026 On output the fully retrieved items are filled in with
2027 values and such. The label was matched, so it never changes.
2028
2029 If an item was not found, its data type is set to none.
2030
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002031 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002032static QCBORError
2033MapSearch(QCBORDecodeContext *pMe, QCBORItem *pItemArray, size_t *puOffset, size_t *puEndOffset)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002034{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002035 QCBORError nReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002036
2037 // TODO: what if pre-order cursor is not at the same level as map? This should be OK.
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002038 if(!DecodeNesting_InMapMode(&(pMe->nesting))) {
2039 return QCBOR_ERR_NOT_ENTERED;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002040 }
2041
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002042 QCBORDecodeNesting SaveNesting;
2043 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002044
2045 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2046
2047 /* Loop over all the items in the map. They could be
2048 * deeply nested and this should handle both definite
2049 * and indefinite length maps and arrays, so this
2050 * adds some complexity. */
Laurence Lundblade64b607e2020-05-13 13:05:57 -07002051 const uint8_t uMapNestLevel = DecodeNesting_GetMapModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002052
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002053 uint_fast8_t uNextNestLevel;
2054
2055 uint64_t uFound = 0;
2056
2057 do {
2058 /* Remember offset because sometims we have to return it */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002059 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002060
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002061 /* Get the item */
2062 QCBORItem Item;
2063 nReturn = QCBORDecode_GetNext(pMe, &Item);
2064 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002065 /* Got non-well-formed CBOR */
2066 goto Done;
2067 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002068
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002069 /* See if item has one of the labels that are of interest */
2070 int i;
2071 QCBORItem *pIterator;
2072 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002073 if(MatchLabel(Item, *pIterator)) {
2074 // A label match has been found
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002075 if(uFound & (0x01ULL << i)) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002076 nReturn = QCBOR_ERR_DUPLICATE_LABEL;
2077 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002078 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002079 if(!MatchType(Item, *pIterator)) {
2080 nReturn = QCBOR_ERR_UNEXPECTED_TYPE;
2081 goto Done;
2082 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002083
2084 /* Successful match. Return the item. */
2085 *pIterator = Item;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002086 uFound |= 0x01ULL << i;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002087 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002088 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002089 }
2090 }
2091 }
2092
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002093 /* Consume the item whether matched or not. This
2094 does th work of traversing maps and array and
2095 everything in them. In this loop only the
2096 items at the current nesting level are examined
2097 to match the labels. */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002098 nReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2099 if(nReturn) {
2100 goto Done;
2101 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002102
2103 } while (uNextNestLevel >= uMapNestLevel);
2104
2105
2106 nReturn = QCBOR_SUCCESS;
2107
2108 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
2109 // Cast OK because encoded CBOR is limited to UINT32_MAX
2110 pMe->uMapEndOffset = (uint32_t)uEndOffset;
2111 // TODO: is zero *puOffset OK?
2112 if(puEndOffset) {
2113 *puEndOffset = uEndOffset;
2114 }
2115
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002116 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002117 int i;
2118 QCBORItem *pIterator;
2119 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
2120 if(!(uFound & (0x01ULL << i))) {
2121 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002122 }
2123 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002124
2125Done:
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002126 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002127
Laurence Lundblade1341c592020-04-11 14:19:05 -07002128 return nReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002129}
2130
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002131
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002132void QCBORDecode_ExitMap(QCBORDecodeContext *pMe)
2133{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002134 size_t uEndOffset;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002135
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002136/*
Laurence Lundblade1341c592020-04-11 14:19:05 -07002137 if(pMe->uMapEndOffset) {
2138 uEndOffset = pMe->uMapEndOffset;
2139 // It is only valid once.
2140 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002141 } else { */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002142 QCBORItem Dummy;
2143
2144 Dummy.uLabelType = QCBOR_TYPE_NONE;
2145
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002146 QCBORError nReturn = MapSearch(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002147
2148 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002149// }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002150
2151 printdecode(pMe, "start exit");
2152 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2153
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002154 DecodeNesting_Exit(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002155 printdecode(pMe, "end exit");
2156
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002157}
2158
2159
2160QCBORError QCBORDecode_GetItemInMap(QCBORDecodeContext *pMe,
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002161 int64_t nLabel,
2162 uint8_t uQcborType,
2163 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002164{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002165 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002166
Laurence Lundblade1341c592020-04-11 14:19:05 -07002167 One[0].uLabelType = QCBOR_TYPE_INT64;
2168 One[0].label.int64 = nLabel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002169 One[0].uDataType = uQcborType;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002170 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2171
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002172 QCBORError nReturn = MapSearch(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002173 if(nReturn) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002174 return nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002175 }
2176
2177 if(One[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002178 return QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002179 }
2180
2181 *pItem = One[0];
2182
2183 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002184}
2185
2186
2187QCBORError QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002188 const char *szLabel,
2189 uint8_t uQcborType,
2190 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002191{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002192 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002193
Laurence Lundblade1341c592020-04-11 14:19:05 -07002194 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2195 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002196 One[0].uDataType = uQcborType;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002197 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2198
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002199 QCBORError nReturn = MapSearch(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002200 if(nReturn) {
2201 return nReturn;
2202 }
2203
2204 if(One[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002205 return QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002206 }
2207
2208 *pItem = One[0];
2209
2210 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002211}
2212
2213
Laurence Lundblade1341c592020-04-11 14:19:05 -07002214
Laurence Lundblade1341c592020-04-11 14:19:05 -07002215
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002216static int FinishEnter(QCBORDecodeContext *pMe, size_t uOffset)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002217{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002218 /* Need to get the current pre-order nesting level and cursor to be
2219 at the first item in the map/array just entered.
2220
2221 Also need to current map nesting level and start cursor to
2222 be at the right place.
2223
2224 The UsefulInBuf offset could be anywhere, so no assumption is
2225 made about it.
2226
2227 No assumption is made about the pre-order nesting level either.
2228
2229 However the map mode nesting level is assumed to be one above
2230 the map level that is being entered.
2231 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002232 /* Seek to the data item that is the map or array */
2233 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002234 pMe->nesting.pCurrent = pMe->nesting.pCurrentMap; // TODO: part of DecodeNesting
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002235
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002236 // TODO: check error?
2237 QCBORDecode_EnterMapMode(pMe, QCBOR_TYPE_MAP);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002238
2239 printdecode(pMe, "Entered Map in Map");
2240
2241 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002242}
2243
2244
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002245QCBORError QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002246{
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002247 /* Use GetItemsInMap to find the map by label, including the
2248 byte offset of it. */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002249 QCBORItem One[2];
Laurence Lundblade1341c592020-04-11 14:19:05 -07002250 One[0].uLabelType = QCBOR_TYPE_INT64;
2251 One[0].label.int64 = nLabel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002252 One[0].uDataType = QCBOR_TYPE_MAP;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002253 One[1].uLabelType = QCBOR_TYPE_NONE;
2254
2255 size_t uOffset;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002256 QCBORError nReturn = MapSearch(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002257 if(nReturn) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002258 return nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002259 }
2260
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002261 /* The map to enter was found, now finish of entering it. */
2262 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002263
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002264 // TODO: error code?
Laurence Lundblade1341c592020-04-11 14:19:05 -07002265 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002266}
2267
2268
2269QCBORError QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2270{
2271 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002272
Laurence Lundblade1341c592020-04-11 14:19:05 -07002273 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2274 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002275 One[0].uDataType = QCBOR_TYPE_MAP;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002276 One[1].uLabelType = QCBOR_TYPE_NONE;
2277
2278 size_t uOffset;
2279
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002280 QCBORError nReturn = MapSearch(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002281
2282 if(nReturn) {
2283 return nReturn;
2284 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002285
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002286 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002287
2288 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002289}
2290
2291
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002292QCBORError QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002293{
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002294 QCBORItem One[2];
2295
2296 One[0].uLabelType = QCBOR_TYPE_INT64;
2297 One[0].label.int64 = nLabel;
2298 One[0].uDataType = QCBOR_TYPE_ARRAY;
2299 One[1].uLabelType = QCBOR_TYPE_NONE;
2300
2301 size_t uOffset;
2302
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002303 QCBORError nReturn = MapSearch(pMe, One, &uOffset, NULL);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002304
2305 if(nReturn != QCBOR_SUCCESS) {
2306 return nReturn;
2307 }
2308
2309 FinishEnter(pMe, uOffset);
2310
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002311 return 0;
2312}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002313
Laurence Lundblade1341c592020-04-11 14:19:05 -07002314
2315QCBORError QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2316{
2317 QCBORItem One[2];
2318
2319 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2320 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002321 One[0].uDataType = QCBOR_TYPE_ARRAY;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002322 One[1].uLabelType = QCBOR_TYPE_NONE;
2323
2324 size_t uOffset;
2325
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002326 QCBORError nReturn = MapSearch(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002327
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002328 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002329 return nReturn;
2330 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002331
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002332 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002333
2334 return 0;
2335}
2336
2337
2338
2339
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002340
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002341/* Next item must be map or this generates an error */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002342QCBORError QCBORDecode_EnterMapMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002343{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002344 QCBORItem Item;
2345 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002346
2347 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002348 nReturn = QCBORDecode_GetNext(pMe, &Item);
2349 if(nReturn != QCBOR_SUCCESS) {
2350 return nReturn;
2351 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002352 if(Item.uDataType != uType) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002353 return QCBOR_ERR_UNEXPECTED_TYPE;
2354 }
2355
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002356 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002357
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002358 printdecode(pMe, "EnterMapDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002359
Laurence Lundblade1341c592020-04-11 14:19:05 -07002360 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002361}
2362
2363
2364
2365QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2366{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002367 return MapSearch(pCtx, pItemList, NULL, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002368}
2369
2370
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002371
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002372
2373
Laurence Lundblade1341c592020-04-11 14:19:05 -07002374void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002375{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002376 // TODO: check for map mode
2377 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2378 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2379}
2380
2381
2382QCBORError QCBORDecode_EnterArray(QCBORDecodeContext *pMe)
2383{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002384 QCBORItem Item;
2385 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002386
2387 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002388 nReturn = QCBORDecode_GetNext(pMe, &Item);
2389 if(nReturn != QCBOR_SUCCESS) {
2390 return nReturn;
2391 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002392 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
2393 return QCBOR_ERR_UNEXPECTED_TYPE;
2394 }
2395
2396 printdecode(pMe, "EnterArray");
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002397
2398 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002399
2400 return QCBOR_SUCCESS;
2401}
2402
2403
2404void QCBORDecode_ExitArray(QCBORDecodeContext *pMe)
2405{
2406 // TODO: make sure we have entered an array
2407 // TODO: combine with code for map? It is the same so far.
2408 size_t uEndOffset;
2409
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002410 /* if(pMe->uMapEndOffset) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002411 uEndOffset = pMe->uMapEndOffset;
2412 // It is only valid once.
2413 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002414 } else {*/
Laurence Lundblade1341c592020-04-11 14:19:05 -07002415 QCBORItem Dummy;
2416
2417 Dummy.uLabelType = QCBOR_TYPE_NONE;
2418
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002419 QCBORError nReturn = MapSearch(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002420
2421 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002422 //}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002423
Laurence Lundblade1341c592020-04-11 14:19:05 -07002424 printdecode(pMe, "start exit");
2425 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2426
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002427 DecodeNesting_Exit(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002428 printdecode(pMe, "end exit");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002429}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002430
Laurence Lundbladee6430642020-03-14 21:15:44 -07002431
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002432void QCBORDecode_GetIntInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, int64_t *pInt)
2433{
2434 // TODO: error handling
2435 QCBORItem Item;
2436 QCBORDecode_GetItemInMapSZ(pMe,szLabel, QCBOR_TYPE_INT64, &Item);
2437 *pInt = Item.val.int64;
2438}
2439
2440void QCBORDecode_GetBstrInMapN(QCBORDecodeContext *pMe, int64_t nLabel, UsefulBufC *pBstr)
2441{
2442 // TODO: error handling
2443 QCBORItem Item;
2444 QCBORDecode_GetItemInMap(pMe, nLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2445 *pBstr = Item.val.string;
2446}
2447
2448void QCBORDecode_GetBstrInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2449{
2450 // TODO: error handling
2451 QCBORItem Item;
2452 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2453 *pBstr = Item.val.string;
2454}
2455
Laurence Lundblade11a064e2020-05-07 13:13:42 -07002456void QCBORDecode_GetDateStringInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2457{
2458 // TODO: error handling
2459 QCBORItem Item;
2460 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_DATE_STRING, &Item);
2461 *pBstr = Item.val.string;
2462}
2463
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002464void QCBORDecode_GetTextInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2465{
2466 // TODO: error handling
2467 QCBORItem Item;
2468 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_TEXT_STRING, &Item);
2469 *pBstr = Item.val.string;
2470}
2471
Laurence Lundbladee6430642020-03-14 21:15:44 -07002472
Laurence Lundbladec4537442020-04-14 18:53:22 -07002473void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002474{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002475 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002476 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07002477 return;
2478 }
2479
Laurence Lundbladec4537442020-04-14 18:53:22 -07002480 QCBORError nError;
2481 QCBORItem Item;
2482
2483 nError = QCBORDecode_GetNext(pMe, &Item);
2484 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002485 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002486 return;
2487 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002488
2489 switch(Item.uDataType) {
2490 case QCBOR_TYPE_TRUE:
2491 *pValue = true;
2492 break;
2493
2494 case QCBOR_TYPE_FALSE:
2495 *pValue = false;
2496 break;
2497
2498 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002499 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002500 break;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002501 }
2502}
2503
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002504#if 0
2505// TODO: fix this
Laurence Lundbladee6430642020-03-14 21:15:44 -07002506/* Types of text strings
2507 * Plain, b64, b64url, URI, regex, MIME Text
2508 * One function for each with options to expect plain?
2509 * One function for all so you can say what you want?
Laurence Lundbladec4537442020-04-14 18:53:22 -07002510 *
2511 * A label is expected if pLabel is not NULL.
Laurence Lundbladee6430642020-03-14 21:15:44 -07002512 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002513void QCBORDecode_GetTextFoo(QCBORDecodeContext *pMe, QCBORLabel *pLabel, UsefulBufC *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002514{
2515 QCBORItem Item;
2516 QCBORError nError;
2517
2518 nError = QCBORDecode_GetNext(pMe, &Item);
2519 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002520 pMe->uLastError = nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002521 return;
2522 }
2523
Laurence Lundbladec4537442020-04-14 18:53:22 -07002524 if(pLabel != NULL) {
2525 if(Item.uLabelType == QCBOR_TYPE_NONE) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002526 pMe->uLastError = 9; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07002527 return;
2528 } else {
2529 // TODO: what about label allocation?
2530 pLabel->uLabelType = Item.uLabelType;
2531 pLabel->label.xx = Item.label.int64; // TOOD: figure out assignment
2532 }
2533 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002534
2535 switch(Item.uDataType) {
2536 case QCBOR_TYPE_TEXT_STRING:
2537 *pValue = Item.val.string;
2538 break;
2539
2540 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002541 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002542 }
2543}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002544#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002545
2546
Laurence Lundbladec4537442020-04-14 18:53:22 -07002547/*
2548 Options for MIME data, CBOR, positive big num, negative big num ??
2549 */
2550void QCBORDecode_GetStringInternal(QCBORDecodeContext *pMe, UsefulBufC *pValue, uint8_t uType)
2551{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002552 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002553 // Already in error state, do nothing
2554 return;
2555 }
2556
2557 QCBORError nError;
2558 QCBORItem Item;
2559
2560 nError = QCBORDecode_GetNext(pMe, &Item);
2561 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002562 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002563 return;
2564 }
2565
2566 if(Item.uDataType == uType) {
2567 *pValue = Item.val.string;
2568 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002569 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002570 }
2571}
2572
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002573void QCBORDecode_GetBytes(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002574{
2575 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_BYTE_STRING);
2576}
2577
2578
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002579void QCBORDecode_GetText(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002580{
2581 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_TEXT_STRING);
2582}
2583
2584
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002585/**
2586 @param[in] bMustBeTagged If \c true, then the data item must be tagged as either
2587 a positive or negative bignum. If \c false, then it only must be a byte string and bIsNegative
2588 will always be false on the asumption that it is positive, but it can be interpretted as
2589 negative if the the sign is know from other context.
2590 @param[out] pValue The bytes that make up the big num
2591 @param[out] pbIsNegative \c true if tagged as a negative big num. \c false otherwise.
2592
2593 if bMustBeTagged is false, then this will succeed if the data item is a plain byte string,
2594 a positive big num or a negative big num.
2595
2596 */
2597void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, bool bMustBeTagged, UsefulBufC *pValue, bool *pbIsNegative)
2598{
2599 if(pMe->uLastError != QCBOR_SUCCESS) {
2600 // Already in error state, do nothing
2601 return;
2602 }
2603
2604 QCBORError nError;
2605 QCBORItem Item;
2606
2607 nError = QCBORDecode_GetNext(pMe, &Item);
2608 if(nError != QCBOR_SUCCESS) {
2609 pMe->uLastError = (uint8_t)nError;
2610 return;
2611 }
2612
2613 *pbIsNegative = false;
2614
2615 switch(Item.uDataType) {
2616 case QCBOR_TYPE_BYTE_STRING:
2617 // TODO: check that there is no tag here?
2618 if(bMustBeTagged) {
2619 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2620 } else {
2621 *pValue = Item.val.string;
2622 }
2623 break;
2624
2625 case QCBOR_TYPE_POSBIGNUM:
2626 *pValue = Item.val.string;
2627 break;
2628
2629 case QCBOR_TYPE_NEGBIGNUM:
2630 *pbIsNegative = true;
2631 *pValue = Item.val.string;
2632 break;
2633
2634 default:
2635 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2636 break;
2637 }
2638}
2639
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002640void QCBORDecode_GetPosBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002641{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002642 // Has to be either a positive big num or a byte string
2643 /*
2644 an array of bytestrings and bignums. Tagging is necessary
2645 to tell them apart
2646
2647 A labeled item where the label tells you it is a big
2648 num and there be no tagging
2649
2650 An array where you expect a big num is the next thing
2651 and it must be tagged so.
2652
2653
2654 Some protocols will require it to be tagged because
2655 it will be ambigous if not.
2656
2657
2658
2659 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002660 // TODO: do these have to be tagged?
2661 // Probably should allow tagged or untagged, but not wrong-tagged
2662 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_POSBIGNUM);
2663}
2664
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002665void QCBORDecode_GetNegBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002666{
2667 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_NEGBIGNUM);
2668}
2669
2670
2671
Laurence Lundbladee6430642020-03-14 21:15:44 -07002672
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002673typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002674
2675
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002676// The main exponentiator that works on only positive numbers
2677static QCBORError Exponentitate10UU(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002678{
2679 uint64_t uResult;
2680
2681 uResult = uMantissa;
2682
2683 /* This loop will run a maximum of 19 times because
2684 * UINT64_MAX < 10 ^^ 19. More than that will cause
2685 * exit with the overflow error
2686 */
2687 while(nExponent > 0) {
2688 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002689 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladec4537442020-04-14 18:53:22 -07002690 }
2691 uResult = uResult * 10;
2692 nExponent--;
2693 }
2694
2695 while(nExponent < 0 ) {
2696 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002697 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
Laurence Lundbladec4537442020-04-14 18:53:22 -07002698 }
2699 uResult = uResult / 10;
2700 nExponent--;
2701 }
2702
2703 *puResult = uResult;
2704
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002705 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002706}
2707
2708
Laurence Lundbladee6430642020-03-14 21:15:44 -07002709/* Convert a decimal fraction to an int64_t without using
2710 floating point or math libraries. Most decimal fractions
2711 will not fit in an int64_t and this will error out with
2712 under or overflow
2713 */
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002714static QCBORError Exponentitate2UU(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002715{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002716 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002717
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002718 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002719
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002720 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07002721 * INT64_MAX < 2^31. More than that will cause
2722 * exist with the overflow error
2723 */
2724 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002725 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002726 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07002727 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002728 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002729 nExponent--;
2730 }
2731
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002732 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002733 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002734 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
2735 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002736 uResult = uResult >> 1;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002737 nExponent--;
2738 }
2739
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002740 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002741
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002742 return QCBOR_SUCCESS;
2743}
2744
2745
2746static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2747{
2748 uint64_t uResult;
2749
2750 // Take the absolute value of the mantissa
2751 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
2752
2753 // Do the exponentiation of the positive mantissa
2754 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
2755 if(uReturn) {
2756 return uReturn;
2757 }
2758
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002759
Laurence Lundblade983500d2020-05-14 11:49:34 -07002760 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
2761 of INT64_MIN. This assumes two's compliment representation where
2762 INT64_MIN is one increment farther from 0 than INT64_MAX.
2763 Trying to write -INT64_MIN doesn't work to get this because the
2764 compiler tries to work with an int64_t which can't represent
2765 -INT64_MIN.
2766 */
2767 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
2768
2769 // Error out if too large
2770 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002771 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2772 }
2773
2774 // Casts are safe because of checks above
2775 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
2776
2777 return QCBOR_SUCCESS;
2778}
2779
2780
2781static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
2782{
2783 if(nMantissa < 0) {
2784 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
2785 }
2786
2787 // Cast to unsigned is OK because of check for negative
2788 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
2789 // Exponentiation is straight forward
2790 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
2791}
2792
2793
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002794#include <math.h>
2795/*
2796static inline uint8_t Exponentitate10F(uint64_t uMantissa, int64_t nExponent, double *pfResult)
2797{
2798 // TODO: checkout exceptions; what is HUGE_VAL?
2799 *pfResult = pow((double)10, (double)nExponent) * (double)uMantissa;
2800
2801 //if(*pfResult == HUGE_VAL)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002802 return 0;
2803}
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002804*/
2805
2806
Laurence Lundbladee6430642020-03-14 21:15:44 -07002807/*
2808 A) bignum is positive
2809 A1) output is signed INT64_MAX
2810 A2) output is unsigned UINT64_MAX
2811 B) bignum is negative
2812 B1) output is signed INT64_MAX
2813 B2) output is unsigned error
2814 */
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002815static inline QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002816{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002817 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002818
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002819 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002820 const uint8_t *pByte = BigNum.ptr;
2821 size_t uLen = BigNum.len;
2822 while(uLen--) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002823 if(uResult > uMax >> 8) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002824 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002825 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002826 uResult = (uResult << 8) + *pByte;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002827 }
2828
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002829 *pResult = uResult;
2830 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002831}
2832
Laurence Lundbladec4537442020-04-14 18:53:22 -07002833
Laurence Lundbladec4537442020-04-14 18:53:22 -07002834
Laurence Lundbladea826c502020-05-10 21:07:00 -07002835static double ConvertBigNumToDouble(const UsefulBufC BigNum)
2836{
2837 double dResult;
2838
2839 dResult = 0.0;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002840 const uint8_t *pByte = BigNum.ptr;
2841 size_t uLen = BigNum.len;
Laurence Lundblade983500d2020-05-14 11:49:34 -07002842 /* This will overflow and become the float value INFINITY if the number
Laurence Lundbladec4537442020-04-14 18:53:22 -07002843 is too large to fit. No error will be logged.
2844 TODO: should an error be logged? */
2845 while(uLen--) {
Laurence Lundblade983500d2020-05-14 11:49:34 -07002846 dResult = (dResult * 256.0) + (double)*pByte;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002847 }
2848
Laurence Lundbladea826c502020-05-10 21:07:00 -07002849 return dResult;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002850}
Laurence Lundbladea826c502020-05-10 21:07:00 -07002851
2852
Laurence Lundbladec4537442020-04-14 18:53:22 -07002853
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002854static inline QCBORError ConvertPositiveBigNumToUnSigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002855{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002856 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002857}
2858
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002859static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002860{
2861 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002862 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
2863 if(uError) {
2864 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002865 }
2866 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2867 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002868 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002869}
2870
2871
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002872static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002873{
2874 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002875 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX-1, &uResult);
2876 if(uError) {
2877 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002878 }
2879 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2880 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002881 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002882}
2883
Laurence Lundbladee6430642020-03-14 21:15:44 -07002884
2885
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002886#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07002887
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002888
2889void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
2890 uint32_t uOptions,
2891 int64_t *pValue,
2892 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002893{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002894 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002895 return;
2896 }
2897
Laurence Lundbladee6430642020-03-14 21:15:44 -07002898 QCBORItem Item;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002899
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002900 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
2901 if(uError) {
2902 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002903 return;
2904 }
2905
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002906 if(pItem) {
2907 *pItem = Item;
2908 }
2909
Laurence Lundbladee6430642020-03-14 21:15:44 -07002910 switch(Item.uDataType) {
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002911 // TODO: float when ifdefs are set
2912 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002913 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002914 // TODO: what about under/overflow here?
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002915 // Invokes the floating-point HW and/or compiler-added libraries
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002916 feclearexcept(FE_ALL_EXCEPT);
Laurence Lundbladea826c502020-05-10 21:07:00 -07002917 *pValue = llround(Item.val.dfnum);
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002918 if(fetestexcept(FE_INVALID)) {
2919 // TODO: better error code
2920 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2921 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002922 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002923 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002924 }
2925 break;
2926
2927 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002928 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002929 *pValue = Item.val.int64;
2930 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002931 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002932 }
2933 break;
2934
2935 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002936 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002937 if(Item.val.uint64 < INT64_MAX) {
2938 *pValue = Item.val.int64;
2939 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002940 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002941 }
2942 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002943 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002944 }
2945 break;
2946
Laurence Lundbladec4537442020-04-14 18:53:22 -07002947 default:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002948 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002949 }
2950}
2951
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002952
Laurence Lundbladec4537442020-04-14 18:53:22 -07002953/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002954 Public function, see header qcbor/qcbor_decode.h file
2955*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07002956void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2957{
2958 QCBORItem Item;
2959
2960 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2961
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002962 if(pMe->uLastError == QCBOR_SUCCESS) {
2963 // The above conversion succeeded
2964 return;
2965 }
2966
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002967 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002968 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07002969 return;
2970 }
2971
2972 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002973
2974 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002975 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002976 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002977 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002978 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002979 }
2980 break;
2981
2982 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002983 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002984 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002985 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002986 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002987 }
2988 break;
2989
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002990#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2991 case QCBOR_TYPE_DECIMAL_FRACTION:
2992 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002993 pMe->uLastError = (uint8_t)ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002994 Item.val.expAndMantissa.nExponent,
2995 pValue,
2996 &Exponentitate10UU);
2997 } else {
2998 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2999 }
3000 break;
3001
3002 case QCBOR_TYPE_BIGFLOAT:
3003 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003004 pMe->uLastError = (uint8_t)ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003005 Item.val.expAndMantissa.nExponent,
3006 pValue,
3007 &Exponentitate2UU);
3008 } else {
3009 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3010 }
3011 break;
3012
3013
Laurence Lundbladee6430642020-03-14 21:15:44 -07003014 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003015 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003016 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003017 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003018 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003019 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003020 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003021 pValue,
3022 &Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003023 }
3024 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003025 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003026 }
3027 break;
3028
3029 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003030 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003031 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003032 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003033 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003034 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003035 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003036 pValue,
3037 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003038 }
3039 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003040 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003041 }
3042 break;
3043
3044 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003045 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003046 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003047 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003048 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003049 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003050 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003051 pValue,
3052 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003053 }
3054 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003055 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003056 }
3057 break;
3058
3059 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003060 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003061 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003062 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003063 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003064 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003065 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003066 pValue,
3067 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003068 }
3069 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003070 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003071 }
3072 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003073
3074 default:
3075 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
3076#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07003077 }
3078}
3079
Laurence Lundbladec4537442020-04-14 18:53:22 -07003080
3081
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003082void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3083 uint32_t uOptions,
3084 uint64_t *pValue,
3085 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003086{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003087 if(pMe->uLastError != QCBOR_SUCCESS) {
3088 return;
3089 }
3090
Laurence Lundbladec4537442020-04-14 18:53:22 -07003091 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003092
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003093 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3094 if(uError) {
3095 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003096 return;
3097 }
3098
Laurence Lundbladea826c502020-05-10 21:07:00 -07003099 if(pItem) {
3100 *pItem = Item;
3101 }
3102
Laurence Lundbladec4537442020-04-14 18:53:22 -07003103 switch(Item.uDataType) {
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003104 // TODO: type flaot
3105 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003106 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003107 feclearexcept(FE_ALL_EXCEPT);
3108 double dRounded = round(Item.val.dfnum);
3109 // TODO: over/underflow
3110 if(fetestexcept(FE_INVALID)) {
3111 // TODO: better error code
3112 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3113 } else if(isnan(dRounded)) {
3114 // TODO: better error code
3115 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3116 } else if(dRounded >= 0) {
3117 *pValue = (uint64_t)dRounded;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003118 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003119 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003120 }
3121 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003122 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003123 }
3124 break;
3125
3126 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003127 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003128 if(Item.val.int64 >= 0) {
3129 *pValue = (uint64_t)Item.val.int64;
3130 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003131 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003132 }
3133 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003134 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003135 }
3136 break;
3137
3138 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003139 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003140 *pValue = Item.val.uint64;
3141 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003142 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003143 }
3144 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003145
3146 default:
3147 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003148 }
3149}
3150
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003151
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003152/*
3153 Public function, see header qcbor/qcbor_decode.h file
3154*/
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003155void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
3156{
3157 QCBORItem Item;
3158
3159 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
3160
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003161 if(pMe->uLastError == QCBOR_SUCCESS) {
3162 // The above conversion succeeded
3163 return;
3164 }
3165
3166 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3167 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07003168 return;
3169 }
3170
Laurence Lundbladee6430642020-03-14 21:15:44 -07003171 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003172
3173 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003174 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003175 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToUnSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003176 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003177 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003178 }
3179 break;
3180
3181 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003182 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade983500d2020-05-14 11:49:34 -07003183 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003184 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003185 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003186 }
3187 break;
3188
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003189#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3190
3191 case QCBOR_TYPE_DECIMAL_FRACTION:
3192 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003193 pMe->uLastError = (uint8_t)ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003194 Item.val.expAndMantissa.nExponent,
3195 pValue,
3196 Exponentitate10UU);
3197 } else {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003198 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003199 }
3200 break;
3201
3202 case QCBOR_TYPE_BIGFLOAT:
3203 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003204 pMe->uLastError = (uint8_t)ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003205 Item.val.expAndMantissa.nExponent,
3206 pValue,
3207 Exponentitate2UU);
3208 } else {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003209 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003210 }
3211 break;
3212
3213
3214
Laurence Lundbladee6430642020-03-14 21:15:44 -07003215 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003216 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003217 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003218 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003219 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003220 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003221 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003222 pValue,
3223 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003224 }
3225 } else {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003226 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003227 }
3228 break;
3229
3230 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003231 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade983500d2020-05-14 11:49:34 -07003232 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003233 } else {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003234 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003235 }
3236 break;
3237
3238 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003239 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003240 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003241 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003242 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003243 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003244 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003245 pValue,
3246 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003247 }
3248 } else {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003249 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003250 }
3251 break;
3252
3253 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003254 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade983500d2020-05-14 11:49:34 -07003255 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003256 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003257 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003258 }
3259 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003260#endif
3261 default:
3262 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003263 }
3264}
3265
Laurence Lundbladec4537442020-04-14 18:53:22 -07003266
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003267void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
3268 uint32_t uOptions,
3269 double *pValue,
3270 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003271{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003272 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003273 return;
3274 }
3275
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003276 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003277
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003278 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003279 if(uError) {
3280 pMe->uLastError = (uint8_t)uError;
3281 return;
3282 }
3283
3284 if(pItem) {
3285 *pItem = Item;
3286 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003287
3288 switch(Item.uDataType) {
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003289 // TODO: float when ifdefs are set
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003290 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003291 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003292 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3293 *pValue = Item.val.dfnum;
3294 } else {
3295 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3296 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003297 }
3298 break;
3299
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003300 case QCBOR_TYPE_INT64:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003301 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003302 // TODO: how does this work?
3303 *pValue = (double)Item.val.int64;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003304
Laurence Lundbladec4537442020-04-14 18:53:22 -07003305 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003306 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003307 }
3308 break;
3309
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003310 case QCBOR_TYPE_UINT64:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003311 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003312 *pValue = (double)Item.val.uint64;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003313 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003314 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003315 }
Laurence Lundblade983500d2020-05-14 11:49:34 -07003316 break;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003317 default:
3318 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
3319 }
3320}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003321
Laurence Lundbladec4537442020-04-14 18:53:22 -07003322
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003323/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003324 Public function, see header qcbor/qcbor_decode.h file
3325*/
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003326void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pValue)
3327{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003328 /*
3329
3330
3331 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
3332
3333 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003334 QCBORItem Item;
3335
3336 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pValue, &Item);
3337
3338 if(pMe->uLastError == QCBOR_SUCCESS) {
3339 // The above conversion succeeded
3340 return;
3341 }
3342
3343 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3344 // The above conversion failed in a way that code below can't correct
3345 return;
3346 }
3347
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003348 pMe->uLastError = QCBOR_SUCCESS;
3349
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003350 switch(Item.uDataType) {
3351 // TODO: type float
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003352 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003353 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3354 // TODO: rounding and overflow errors
3355 *pValue = (double)Item.val.expAndMantissa.Mantissa.nInt *
3356 pow(10.0, (double)Item.val.expAndMantissa.nExponent);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003357 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003358 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003359 }
3360 break;
3361
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003362 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003363 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
3364 *pValue = (double)Item.val.expAndMantissa.Mantissa.nInt *
3365 exp2((double)Item.val.expAndMantissa.nExponent);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003366 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003367 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003368 }
3369 break;
3370
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003371 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003372 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3373 *pValue = ConvertBigNumToDouble(Item.val.bigNum);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003374 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003375 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003376 }
3377 break;
3378
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003379 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003380 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3381 *pValue = -ConvertBigNumToDouble(Item.val.bigNum);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003382 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003383 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003384 }
3385 break;
3386
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003387 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003388 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3389 double dMantissa = ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
3390 *pValue = dMantissa * pow(10, (double)Item.val.expAndMantissa.nExponent);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003391 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003392 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003393 }
3394 break;
3395
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003396 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3397 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3398 double dMantissa = -ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
3399 *pValue = dMantissa * pow(10, (double)Item.val.expAndMantissa.nExponent);
Laurence Lundblade983500d2020-05-14 11:49:34 -07003400 } else {
3401 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3402 }
3403 break;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003404
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003405 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3406 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3407 double dMantissa = ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
3408 *pValue = dMantissa * exp2((double)Item.val.expAndMantissa.nExponent);
Laurence Lundblade983500d2020-05-14 11:49:34 -07003409 } else {
3410 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3411 }
3412 break;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003413
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003414 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3415 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3416 double dMantissa = -ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
3417 *pValue = dMantissa * exp2((double)Item.val.expAndMantissa.nExponent);
Laurence Lundblade983500d2020-05-14 11:49:34 -07003418 } else {
3419 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3420 }
3421 break;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003422
3423 default:
3424 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003425 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07003426}
3427