blob: c418677c53ad9eb551aabbdd44e42eb4ecc5cd79 [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 Lundblade34691b92020-05-18 22:25:25 -07002132void QCBORDecode_ExitMapMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002133{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002134 size_t uEndOffset;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002135
Laurence Lundblade34691b92020-05-18 22:25:25 -07002136 (void)uType; // TODO: error check
2137
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002138/*
Laurence Lundblade1341c592020-04-11 14:19:05 -07002139 if(pMe->uMapEndOffset) {
2140 uEndOffset = pMe->uMapEndOffset;
2141 // It is only valid once.
2142 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002143 } else { */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002144 QCBORItem Dummy;
2145
2146 Dummy.uLabelType = QCBOR_TYPE_NONE;
2147
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002148 QCBORError nReturn = MapSearch(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002149
2150 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002151// }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002152
2153 printdecode(pMe, "start exit");
2154 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2155
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002156 DecodeNesting_Exit(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002157 printdecode(pMe, "end exit");
2158
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002159}
2160
2161
2162QCBORError QCBORDecode_GetItemInMap(QCBORDecodeContext *pMe,
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002163 int64_t nLabel,
2164 uint8_t uQcborType,
2165 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002166{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002167 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002168
Laurence Lundblade1341c592020-04-11 14:19:05 -07002169 One[0].uLabelType = QCBOR_TYPE_INT64;
2170 One[0].label.int64 = nLabel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002171 One[0].uDataType = uQcborType;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002172 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2173
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002174 QCBORError nReturn = MapSearch(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002175 if(nReturn) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002176 return nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002177 }
2178
2179 if(One[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002180 return QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002181 }
2182
2183 *pItem = One[0];
2184
2185 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002186}
2187
2188
2189QCBORError QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002190 const char *szLabel,
2191 uint8_t uQcborType,
2192 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002193{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002194 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002195
Laurence Lundblade1341c592020-04-11 14:19:05 -07002196 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2197 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002198 One[0].uDataType = uQcborType;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002199 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2200
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002201 QCBORError nReturn = MapSearch(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002202 if(nReturn) {
2203 return nReturn;
2204 }
2205
2206 if(One[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002207 return QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002208 }
2209
2210 *pItem = One[0];
2211
2212 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002213}
2214
2215
Laurence Lundblade1341c592020-04-11 14:19:05 -07002216
Laurence Lundblade1341c592020-04-11 14:19:05 -07002217
Laurence Lundblade34691b92020-05-18 22:25:25 -07002218static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002219{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002220 if(pMe->uLastError != QCBOR_SUCCESS) {
2221 // Already in error state; do nothing.
2222 return;
2223 }
2224
2225 size_t uOffset;
2226 pMe->uLastError = MapSearch(pMe, pSearch, &uOffset, NULL);
2227 if(pMe->uLastError != QCBOR_SUCCESS) {
2228 return;
2229 }
2230
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002231 /* Need to get the current pre-order nesting level and cursor to be
2232 at the first item in the map/array just entered.
2233
2234 Also need to current map nesting level and start cursor to
2235 be at the right place.
2236
2237 The UsefulInBuf offset could be anywhere, so no assumption is
2238 made about it.
2239
2240 No assumption is made about the pre-order nesting level either.
2241
2242 However the map mode nesting level is assumed to be one above
2243 the map level that is being entered.
2244 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002245 /* Seek to the data item that is the map or array */
2246 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002247 pMe->nesting.pCurrent = pMe->nesting.pCurrentMap; // TODO: part of DecodeNesting
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002248
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002249 // TODO: check error?
Laurence Lundblade34691b92020-05-18 22:25:25 -07002250 QCBORDecode_EnterMapMode(pMe, pSearch->uDataType);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002251
Laurence Lundblade34691b92020-05-18 22:25:25 -07002252 printdecode(pMe, "FinishEnter");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002253}
2254
2255
Laurence Lundblade34691b92020-05-18 22:25:25 -07002256void QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002257{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002258 QCBORItem One[2];
Laurence Lundblade1341c592020-04-11 14:19:05 -07002259 One[0].uLabelType = QCBOR_TYPE_INT64;
2260 One[0].label.int64 = nLabel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002261 One[0].uDataType = QCBOR_TYPE_MAP;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002262 One[1].uLabelType = QCBOR_TYPE_NONE;
2263
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002264 /* The map to enter was found, now finish of entering it. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002265 SearchAndEnter(pMe, One);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002266}
2267
2268
Laurence Lundblade34691b92020-05-18 22:25:25 -07002269void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002270{
2271 QCBORItem One[2];
Laurence Lundblade1341c592020-04-11 14:19:05 -07002272 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2273 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002274 One[0].uDataType = QCBOR_TYPE_MAP;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002275 One[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002276
Laurence Lundblade34691b92020-05-18 22:25:25 -07002277 SearchAndEnter(pMe, One);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002278}
2279
2280
Laurence Lundblade34691b92020-05-18 22:25:25 -07002281void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002282{
2283 QCBORItem One[2];
Laurence Lundblade34691b92020-05-18 22:25:25 -07002284 One[0].uLabelType = QCBOR_TYPE_INT64;
2285 One[0].label.int64 = nLabel;
2286 One[0].uDataType = QCBOR_TYPE_ARRAY;
2287 One[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002288
Laurence Lundblade34691b92020-05-18 22:25:25 -07002289 SearchAndEnter(pMe, One);
2290}
2291
2292
2293void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2294{
2295 QCBORItem One[2];
Laurence Lundblade1341c592020-04-11 14:19:05 -07002296 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2297 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002298 One[0].uDataType = QCBOR_TYPE_ARRAY;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002299 One[1].uLabelType = QCBOR_TYPE_NONE;
2300
Laurence Lundblade34691b92020-05-18 22:25:25 -07002301 SearchAndEnter(pMe, One);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002302}
2303
2304
2305
2306
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002307
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002308/* Next item must be map or this generates an error */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002309void QCBORDecode_EnterMapMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002310{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002311 if(pMe->uLastError != QCBOR_SUCCESS) {
2312 // Already in error state; do nothing.
2313 return;
2314 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002315
2316 /* Get the data item that is the map that is being searched */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002317 QCBORItem Item;
2318 pMe->uLastError = QCBORDecode_GetNext(pMe, &Item);
2319 if(pMe->uLastError != QCBOR_SUCCESS) {
2320 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002321 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002322 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002323 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2324 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002325 }
2326
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002327 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002328
Laurence Lundblade34691b92020-05-18 22:25:25 -07002329 printdecode(pMe, "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002330}
2331
2332
2333
2334QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2335{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002336 return MapSearch(pCtx, pItemList, NULL, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002337}
2338
2339
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002340
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002341
2342
Laurence Lundblade1341c592020-04-11 14:19:05 -07002343void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002344{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002345 // TODO: check for map mode
2346 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2347 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2348}
2349
2350
Laurence Lundblade1341c592020-04-11 14:19:05 -07002351
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002352
Laurence Lundbladee6430642020-03-14 21:15:44 -07002353
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002354void QCBORDecode_GetIntInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, int64_t *pInt)
2355{
2356 // TODO: error handling
2357 QCBORItem Item;
2358 QCBORDecode_GetItemInMapSZ(pMe,szLabel, QCBOR_TYPE_INT64, &Item);
2359 *pInt = Item.val.int64;
2360}
2361
2362void QCBORDecode_GetBstrInMapN(QCBORDecodeContext *pMe, int64_t nLabel, UsefulBufC *pBstr)
2363{
2364 // TODO: error handling
2365 QCBORItem Item;
2366 QCBORDecode_GetItemInMap(pMe, nLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2367 *pBstr = Item.val.string;
2368}
2369
2370void QCBORDecode_GetBstrInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2371{
2372 // TODO: error handling
2373 QCBORItem Item;
2374 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2375 *pBstr = Item.val.string;
2376}
2377
Laurence Lundblade11a064e2020-05-07 13:13:42 -07002378void QCBORDecode_GetDateStringInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2379{
2380 // TODO: error handling
2381 QCBORItem Item;
2382 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_DATE_STRING, &Item);
2383 *pBstr = Item.val.string;
2384}
2385
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002386void QCBORDecode_GetTextInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2387{
2388 // TODO: error handling
2389 QCBORItem Item;
2390 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_TEXT_STRING, &Item);
2391 *pBstr = Item.val.string;
2392}
2393
Laurence Lundbladee6430642020-03-14 21:15:44 -07002394
Laurence Lundbladec4537442020-04-14 18:53:22 -07002395void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002396{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002397 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002398 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07002399 return;
2400 }
2401
Laurence Lundbladec4537442020-04-14 18:53:22 -07002402 QCBORError nError;
2403 QCBORItem Item;
2404
2405 nError = QCBORDecode_GetNext(pMe, &Item);
2406 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002407 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002408 return;
2409 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002410
2411 switch(Item.uDataType) {
2412 case QCBOR_TYPE_TRUE:
2413 *pValue = true;
2414 break;
2415
2416 case QCBOR_TYPE_FALSE:
2417 *pValue = false;
2418 break;
2419
2420 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002421 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002422 break;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002423 }
2424}
2425
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002426#if 0
2427// TODO: fix this
Laurence Lundbladee6430642020-03-14 21:15:44 -07002428/* Types of text strings
2429 * Plain, b64, b64url, URI, regex, MIME Text
2430 * One function for each with options to expect plain?
2431 * One function for all so you can say what you want?
Laurence Lundbladec4537442020-04-14 18:53:22 -07002432 *
2433 * A label is expected if pLabel is not NULL.
Laurence Lundbladee6430642020-03-14 21:15:44 -07002434 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002435void QCBORDecode_GetTextFoo(QCBORDecodeContext *pMe, QCBORLabel *pLabel, UsefulBufC *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002436{
2437 QCBORItem Item;
2438 QCBORError nError;
2439
2440 nError = QCBORDecode_GetNext(pMe, &Item);
2441 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002442 pMe->uLastError = nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002443 return;
2444 }
2445
Laurence Lundbladec4537442020-04-14 18:53:22 -07002446 if(pLabel != NULL) {
2447 if(Item.uLabelType == QCBOR_TYPE_NONE) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002448 pMe->uLastError = 9; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07002449 return;
2450 } else {
2451 // TODO: what about label allocation?
2452 pLabel->uLabelType = Item.uLabelType;
2453 pLabel->label.xx = Item.label.int64; // TOOD: figure out assignment
2454 }
2455 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002456
2457 switch(Item.uDataType) {
2458 case QCBOR_TYPE_TEXT_STRING:
2459 *pValue = Item.val.string;
2460 break;
2461
2462 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002463 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002464 }
2465}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002466#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002467
2468
Laurence Lundbladec4537442020-04-14 18:53:22 -07002469/*
2470 Options for MIME data, CBOR, positive big num, negative big num ??
2471 */
2472void QCBORDecode_GetStringInternal(QCBORDecodeContext *pMe, UsefulBufC *pValue, uint8_t uType)
2473{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002474 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002475 // Already in error state, do nothing
2476 return;
2477 }
2478
2479 QCBORError nError;
2480 QCBORItem Item;
2481
2482 nError = QCBORDecode_GetNext(pMe, &Item);
2483 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002484 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002485 return;
2486 }
2487
2488 if(Item.uDataType == uType) {
2489 *pValue = Item.val.string;
2490 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002491 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002492 }
2493}
2494
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002495void QCBORDecode_GetBytes(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002496{
2497 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_BYTE_STRING);
2498}
2499
2500
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002501void QCBORDecode_GetText(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002502{
2503 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_TEXT_STRING);
2504}
2505
2506
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002507/**
2508 @param[in] bMustBeTagged If \c true, then the data item must be tagged as either
2509 a positive or negative bignum. If \c false, then it only must be a byte string and bIsNegative
2510 will always be false on the asumption that it is positive, but it can be interpretted as
2511 negative if the the sign is know from other context.
2512 @param[out] pValue The bytes that make up the big num
2513 @param[out] pbIsNegative \c true if tagged as a negative big num. \c false otherwise.
2514
2515 if bMustBeTagged is false, then this will succeed if the data item is a plain byte string,
2516 a positive big num or a negative big num.
2517
2518 */
2519void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, bool bMustBeTagged, UsefulBufC *pValue, bool *pbIsNegative)
2520{
2521 if(pMe->uLastError != QCBOR_SUCCESS) {
2522 // Already in error state, do nothing
2523 return;
2524 }
2525
2526 QCBORError nError;
2527 QCBORItem Item;
2528
2529 nError = QCBORDecode_GetNext(pMe, &Item);
2530 if(nError != QCBOR_SUCCESS) {
2531 pMe->uLastError = (uint8_t)nError;
2532 return;
2533 }
2534
2535 *pbIsNegative = false;
2536
2537 switch(Item.uDataType) {
2538 case QCBOR_TYPE_BYTE_STRING:
2539 // TODO: check that there is no tag here?
2540 if(bMustBeTagged) {
2541 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2542 } else {
2543 *pValue = Item.val.string;
2544 }
2545 break;
2546
2547 case QCBOR_TYPE_POSBIGNUM:
2548 *pValue = Item.val.string;
2549 break;
2550
2551 case QCBOR_TYPE_NEGBIGNUM:
2552 *pbIsNegative = true;
2553 *pValue = Item.val.string;
2554 break;
2555
2556 default:
2557 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2558 break;
2559 }
2560}
2561
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002562void QCBORDecode_GetPosBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002563{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002564 // Has to be either a positive big num or a byte string
2565 /*
2566 an array of bytestrings and bignums. Tagging is necessary
2567 to tell them apart
2568
2569 A labeled item where the label tells you it is a big
2570 num and there be no tagging
2571
2572 An array where you expect a big num is the next thing
2573 and it must be tagged so.
2574
2575
2576 Some protocols will require it to be tagged because
2577 it will be ambigous if not.
2578
2579
2580
2581 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002582 // TODO: do these have to be tagged?
2583 // Probably should allow tagged or untagged, but not wrong-tagged
2584 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_POSBIGNUM);
2585}
2586
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002587void QCBORDecode_GetNegBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002588{
2589 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_NEGBIGNUM);
2590}
2591
2592
2593
Laurence Lundbladee6430642020-03-14 21:15:44 -07002594
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002595typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002596
2597
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002598// The main exponentiator that works on only positive numbers
2599static QCBORError Exponentitate10UU(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002600{
2601 uint64_t uResult;
2602
2603 uResult = uMantissa;
2604
2605 /* This loop will run a maximum of 19 times because
2606 * UINT64_MAX < 10 ^^ 19. More than that will cause
2607 * exit with the overflow error
2608 */
Laurence Lundblade887add82020-05-17 05:50:34 -07002609 while(nExponent > 1) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002610 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002611 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladec4537442020-04-14 18:53:22 -07002612 }
2613 uResult = uResult * 10;
2614 nExponent--;
2615 }
2616
2617 while(nExponent < 0 ) {
2618 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002619 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
Laurence Lundbladec4537442020-04-14 18:53:22 -07002620 }
2621 uResult = uResult / 10;
2622 nExponent--;
2623 }
2624
2625 *puResult = uResult;
2626
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002627 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002628}
2629
2630
Laurence Lundbladee6430642020-03-14 21:15:44 -07002631/* Convert a decimal fraction to an int64_t without using
2632 floating point or math libraries. Most decimal fractions
2633 will not fit in an int64_t and this will error out with
2634 under or overflow
2635 */
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002636static QCBORError Exponentitate2UU(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002637{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002638 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002639
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002640 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002641
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002642 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07002643 * INT64_MAX < 2^31. More than that will cause
2644 * exist with the overflow error
2645 */
2646 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002647 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002648 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07002649 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002650 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002651 nExponent--;
2652 }
2653
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002654 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002655 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002656 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
2657 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002658 uResult = uResult >> 1;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002659 nExponent--;
2660 }
2661
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002662 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002663
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002664 return QCBOR_SUCCESS;
2665}
2666
2667
2668static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2669{
2670 uint64_t uResult;
2671
2672 // Take the absolute value of the mantissa
2673 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
2674
2675 // Do the exponentiation of the positive mantissa
2676 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
2677 if(uReturn) {
2678 return uReturn;
2679 }
2680
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002681
Laurence Lundblade983500d2020-05-14 11:49:34 -07002682 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
2683 of INT64_MIN. This assumes two's compliment representation where
2684 INT64_MIN is one increment farther from 0 than INT64_MAX.
2685 Trying to write -INT64_MIN doesn't work to get this because the
2686 compiler tries to work with an int64_t which can't represent
2687 -INT64_MIN.
2688 */
2689 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
2690
2691 // Error out if too large
2692 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002693 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2694 }
2695
2696 // Casts are safe because of checks above
2697 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
2698
2699 return QCBOR_SUCCESS;
2700}
2701
2702
2703static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
2704{
2705 if(nMantissa < 0) {
2706 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
2707 }
2708
2709 // Cast to unsigned is OK because of check for negative
2710 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
2711 // Exponentiation is straight forward
2712 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
2713}
2714
2715
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002716#include <math.h>
2717/*
2718static inline uint8_t Exponentitate10F(uint64_t uMantissa, int64_t nExponent, double *pfResult)
2719{
2720 // TODO: checkout exceptions; what is HUGE_VAL?
2721 *pfResult = pow((double)10, (double)nExponent) * (double)uMantissa;
2722
2723 //if(*pfResult == HUGE_VAL)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002724 return 0;
2725}
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002726*/
2727
2728
Laurence Lundbladee6430642020-03-14 21:15:44 -07002729/*
2730 A) bignum is positive
2731 A1) output is signed INT64_MAX
2732 A2) output is unsigned UINT64_MAX
2733 B) bignum is negative
2734 B1) output is signed INT64_MAX
2735 B2) output is unsigned error
2736 */
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002737static inline QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002738{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002739 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002740
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002741 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002742 const uint8_t *pByte = BigNum.ptr;
2743 size_t uLen = BigNum.len;
2744 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07002745 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002746 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002747 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07002748 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002749 }
2750
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002751 *pResult = uResult;
2752 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002753}
2754
Laurence Lundbladec4537442020-04-14 18:53:22 -07002755
Laurence Lundbladec4537442020-04-14 18:53:22 -07002756
Laurence Lundbladea826c502020-05-10 21:07:00 -07002757static double ConvertBigNumToDouble(const UsefulBufC BigNum)
2758{
2759 double dResult;
2760
2761 dResult = 0.0;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002762 const uint8_t *pByte = BigNum.ptr;
2763 size_t uLen = BigNum.len;
Laurence Lundblade983500d2020-05-14 11:49:34 -07002764 /* This will overflow and become the float value INFINITY if the number
Laurence Lundbladec4537442020-04-14 18:53:22 -07002765 is too large to fit. No error will be logged.
2766 TODO: should an error be logged? */
2767 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07002768 dResult = (dResult * 256.0) + (double)*pByte++;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002769 }
2770
Laurence Lundbladea826c502020-05-10 21:07:00 -07002771 return dResult;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002772}
Laurence Lundbladea826c502020-05-10 21:07:00 -07002773
2774
Laurence Lundbladec4537442020-04-14 18:53:22 -07002775
Laurence Lundblade887add82020-05-17 05:50:34 -07002776static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002777{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002778 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002779}
2780
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002781static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002782{
2783 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002784 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
2785 if(uError) {
2786 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002787 }
2788 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2789 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002790 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002791}
2792
2793
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002794static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002795{
2796 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002797 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX-1, &uResult);
2798 if(uError) {
2799 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002800 }
2801 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07002802 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladee6430642020-03-14 21:15:44 -07002803 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002804 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002805}
2806
Laurence Lundbladee6430642020-03-14 21:15:44 -07002807
2808
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002809#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07002810
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002811
2812void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
2813 uint32_t uOptions,
2814 int64_t *pValue,
2815 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002816{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002817 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002818 return;
2819 }
2820
Laurence Lundbladee6430642020-03-14 21:15:44 -07002821 QCBORItem Item;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002822
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002823 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
2824 if(uError) {
2825 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002826 return;
2827 }
2828
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002829 if(pItem) {
2830 *pItem = Item;
2831 }
2832
Laurence Lundbladee6430642020-03-14 21:15:44 -07002833 switch(Item.uDataType) {
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002834 // TODO: float when ifdefs are set
2835 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002836 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002837 // TODO: what about under/overflow here?
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002838 // Invokes the floating-point HW and/or compiler-added libraries
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002839 feclearexcept(FE_ALL_EXCEPT);
Laurence Lundbladea826c502020-05-10 21:07:00 -07002840 *pValue = llround(Item.val.dfnum);
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002841 if(fetestexcept(FE_INVALID)) {
2842 // TODO: better error code
2843 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2844 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002845 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002846 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002847 }
2848 break;
2849
2850 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002851 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002852 *pValue = Item.val.int64;
2853 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002854 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002855 }
2856 break;
2857
2858 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002859 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002860 if(Item.val.uint64 < INT64_MAX) {
2861 *pValue = Item.val.int64;
2862 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002863 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002864 }
2865 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002866 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002867 }
2868 break;
2869
Laurence Lundbladec4537442020-04-14 18:53:22 -07002870 default:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002871 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002872 }
2873}
2874
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002875
Laurence Lundbladec4537442020-04-14 18:53:22 -07002876/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002877 Public function, see header qcbor/qcbor_decode.h file
2878*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07002879void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2880{
2881 QCBORItem Item;
2882
2883 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2884
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002885 if(pMe->uLastError == QCBOR_SUCCESS) {
2886 // The above conversion succeeded
2887 return;
2888 }
2889
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002890 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002891 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07002892 return;
2893 }
2894
2895 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002896
2897 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002898 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002899 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002900 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002901 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002902 }
2903 break;
2904
2905 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002906 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002907 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002908 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002909 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002910 }
2911 break;
2912
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002913#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2914 case QCBOR_TYPE_DECIMAL_FRACTION:
2915 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002916 pMe->uLastError = (uint8_t)ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002917 Item.val.expAndMantissa.nExponent,
2918 pValue,
2919 &Exponentitate10UU);
2920 } else {
2921 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2922 }
2923 break;
2924
2925 case QCBOR_TYPE_BIGFLOAT:
2926 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002927 pMe->uLastError = (uint8_t)ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002928 Item.val.expAndMantissa.nExponent,
2929 pValue,
2930 &Exponentitate2UU);
2931 } else {
2932 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2933 }
2934 break;
2935
2936
Laurence Lundbladee6430642020-03-14 21:15:44 -07002937 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002938 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002939 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002940 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002941 if(!pMe->uLastError) {
Laurence Lundblade887add82020-05-17 05:50:34 -07002942 int64_t nMultiplier;
2943 pMe->uLastError = (uint8_t)ExponentiateNN(10,
2944 Item.val.expAndMantissa.nExponent,
2945 &nMultiplier,
2946 &Exponentitate10UU);
2947 if(!pMe->uLastError) {
2948 // TODO: overflow
2949 *pValue = nMantissa * nMultiplier;
2950 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002951 }
2952 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002953 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002954 }
2955 break;
2956
2957 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002958 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002959 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002960 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002961 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002962 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002963 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002964 pValue,
2965 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002966 }
2967 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002968 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002969 }
2970 break;
2971
2972 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002973 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002974 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002975 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002976 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002977 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002978 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002979 pValue,
2980 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002981 }
2982 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002983 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002984 }
2985 break;
2986
2987 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002988 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002989 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002990 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002991 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002992 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002993 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002994 pValue,
2995 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002996 }
2997 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002998 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002999 }
3000 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003001
3002 default:
3003 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
3004#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07003005 }
3006}
3007
Laurence Lundbladec4537442020-04-14 18:53:22 -07003008
3009
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003010void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3011 uint32_t uOptions,
3012 uint64_t *pValue,
3013 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003014{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003015 if(pMe->uLastError != QCBOR_SUCCESS) {
3016 return;
3017 }
3018
Laurence Lundbladec4537442020-04-14 18:53:22 -07003019 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003020
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003021 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3022 if(uError) {
3023 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003024 return;
3025 }
3026
Laurence Lundbladea826c502020-05-10 21:07:00 -07003027 if(pItem) {
3028 *pItem = Item;
3029 }
3030
Laurence Lundbladec4537442020-04-14 18:53:22 -07003031 switch(Item.uDataType) {
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003032 // TODO: type flaot
3033 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003034 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003035 feclearexcept(FE_ALL_EXCEPT);
3036 double dRounded = round(Item.val.dfnum);
3037 // TODO: over/underflow
3038 if(fetestexcept(FE_INVALID)) {
3039 // TODO: better error code
3040 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3041 } else if(isnan(dRounded)) {
3042 // TODO: better error code
3043 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3044 } else if(dRounded >= 0) {
3045 *pValue = (uint64_t)dRounded;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003046 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003047 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003048 }
3049 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003050 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003051 }
3052 break;
3053
3054 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003055 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003056 if(Item.val.int64 >= 0) {
3057 *pValue = (uint64_t)Item.val.int64;
3058 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003059 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003060 }
3061 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003062 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003063 }
3064 break;
3065
3066 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003067 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003068 *pValue = Item.val.uint64;
3069 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003070 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003071 }
3072 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003073
3074 default:
3075 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003076 }
3077}
3078
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003079
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003080/*
3081 Public function, see header qcbor/qcbor_decode.h file
3082*/
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003083void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
3084{
3085 QCBORItem Item;
3086
3087 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
3088
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003089 if(pMe->uLastError == QCBOR_SUCCESS) {
3090 // The above conversion succeeded
3091 return;
3092 }
3093
3094 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3095 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07003096 return;
3097 }
3098
Laurence Lundbladee6430642020-03-14 21:15:44 -07003099 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003100
3101 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003102 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade887add82020-05-17 05:50:34 -07003103 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToUnsigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003104 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003105 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003106 }
3107 break;
3108
3109 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003110 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade983500d2020-05-14 11:49:34 -07003111 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003112 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003113 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003114 }
3115 break;
3116
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003117#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3118
3119 case QCBOR_TYPE_DECIMAL_FRACTION:
3120 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003121 pMe->uLastError = (uint8_t)ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003122 Item.val.expAndMantissa.nExponent,
3123 pValue,
3124 Exponentitate10UU);
3125 } else {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003126 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003127 }
3128 break;
3129
3130 case QCBOR_TYPE_BIGFLOAT:
3131 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003132 pMe->uLastError = (uint8_t)ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003133 Item.val.expAndMantissa.nExponent,
3134 pValue,
3135 Exponentitate2UU);
3136 } else {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003137 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003138 }
3139 break;
3140
3141
3142
Laurence Lundbladee6430642020-03-14 21:15:44 -07003143 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003144 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade887add82020-05-17 05:50:34 -07003145 uint64_t uMantissa;
3146 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToUnsigned(Item.val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003147 if(!pMe->uLastError) {
Laurence Lundblade887add82020-05-17 05:50:34 -07003148 uint64_t uMultiplier;
3149 pMe->uLastError = (uint8_t)ExponentitateNU(10,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003150 Item.val.expAndMantissa.nExponent,
Laurence Lundblade887add82020-05-17 05:50:34 -07003151 &uMultiplier,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003152 Exponentitate10UU);
Laurence Lundblade887add82020-05-17 05:50:34 -07003153 if(!pMe->uLastError) {
3154 *pValue = uMantissa * uMultiplier;
3155 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07003156 }
3157 } else {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003158 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003159 }
3160 break;
3161
3162 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003163 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade983500d2020-05-14 11:49:34 -07003164 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003165 } else {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003166 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003167 }
3168 break;
3169
3170 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003171 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003172 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003173 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003174 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003175 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003176 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003177 pValue,
3178 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003179 }
3180 } else {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003181 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003182 }
3183 break;
3184
3185 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003186 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade983500d2020-05-14 11:49:34 -07003187 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003188 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003189 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003190 }
3191 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003192#endif
3193 default:
3194 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003195 }
3196}
3197
Laurence Lundbladec4537442020-04-14 18:53:22 -07003198
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003199void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
3200 uint32_t uOptions,
3201 double *pValue,
3202 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003203{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003204 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003205 return;
3206 }
3207
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003208 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003209
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003210 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003211 if(uError) {
3212 pMe->uLastError = (uint8_t)uError;
3213 return;
3214 }
3215
3216 if(pItem) {
3217 *pItem = Item;
3218 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003219
3220 switch(Item.uDataType) {
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003221 // TODO: float when ifdefs are set
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003222 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003223 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003224 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3225 *pValue = Item.val.dfnum;
3226 } else {
3227 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3228 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003229 }
3230 break;
3231
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003232 case QCBOR_TYPE_INT64:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003233 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003234 // TODO: how does this work?
3235 *pValue = (double)Item.val.int64;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003236
Laurence Lundbladec4537442020-04-14 18:53:22 -07003237 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003238 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003239 }
3240 break;
3241
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003242 case QCBOR_TYPE_UINT64:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003243 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003244 *pValue = (double)Item.val.uint64;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003245 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003246 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003247 }
Laurence Lundblade983500d2020-05-14 11:49:34 -07003248 break;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003249 default:
3250 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
3251 }
3252}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003253
Laurence Lundbladec4537442020-04-14 18:53:22 -07003254
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003255/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003256 Public function, see header qcbor/qcbor_decode.h file
3257*/
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003258void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pValue)
3259{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003260 /*
3261
3262
3263 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
3264
3265 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003266 QCBORItem Item;
3267
3268 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pValue, &Item);
3269
3270 if(pMe->uLastError == QCBOR_SUCCESS) {
3271 // The above conversion succeeded
3272 return;
3273 }
3274
3275 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3276 // The above conversion failed in a way that code below can't correct
3277 return;
3278 }
3279
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003280 pMe->uLastError = QCBOR_SUCCESS;
3281
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003282 switch(Item.uDataType) {
3283 // TODO: type float
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003284 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003285 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3286 // TODO: rounding and overflow errors
3287 *pValue = (double)Item.val.expAndMantissa.Mantissa.nInt *
3288 pow(10.0, (double)Item.val.expAndMantissa.nExponent);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003289 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003290 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003291 }
3292 break;
3293
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003294 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003295 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
3296 *pValue = (double)Item.val.expAndMantissa.Mantissa.nInt *
3297 exp2((double)Item.val.expAndMantissa.nExponent);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003298 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003299 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003300 }
3301 break;
3302
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003303 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003304 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3305 *pValue = ConvertBigNumToDouble(Item.val.bigNum);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003306 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003307 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003308 }
3309 break;
3310
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003311 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003312 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3313 *pValue = -ConvertBigNumToDouble(Item.val.bigNum);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003314 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003315 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003316 }
3317 break;
3318
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003319 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003320 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3321 double dMantissa = ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
3322 *pValue = dMantissa * pow(10, (double)Item.val.expAndMantissa.nExponent);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003323 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003324 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003325 }
3326 break;
3327
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003328 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3329 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3330 double dMantissa = -ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
3331 *pValue = dMantissa * pow(10, (double)Item.val.expAndMantissa.nExponent);
Laurence Lundblade983500d2020-05-14 11:49:34 -07003332 } else {
3333 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3334 }
3335 break;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003336
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003337 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3338 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3339 double dMantissa = ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
3340 *pValue = dMantissa * exp2((double)Item.val.expAndMantissa.nExponent);
Laurence Lundblade983500d2020-05-14 11:49:34 -07003341 } else {
3342 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3343 }
3344 break;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003345
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003346 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3347 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3348 double dMantissa = -ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
3349 *pValue = dMantissa * exp2((double)Item.val.expAndMantissa.nExponent);
Laurence Lundblade983500d2020-05-14 11:49:34 -07003350 } else {
3351 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3352 }
3353 break;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003354
3355 default:
3356 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003357 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07003358}
3359