blob: a061dc6f71db6fb28ae5e872dd8d4b19c7eb104d [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 Lundblade9c905e82020-04-25 11:31:38 -0700138 if(pNesting->pCurrent->uMapMode) {
139 if(pNesting->pCurrent->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{
163 return (bool)pNesting->pCurrent->uMapMode;
164}
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 Lundbladeee851742020-01-08 08:37:05 -0800174inline static int
175DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700176{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700177 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700178 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700179 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800180
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700181 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
182}
183
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800184// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800185inline static QCBORError
186DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700187{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800188 // breaks must always occur when there is nesting
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700189 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800190 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700191 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800192
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800193 // breaks can only occur when the map/array is indefinite length
194 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
195 return QCBOR_ERR_BAD_BREAK;
196 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800197
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800198 // if all OK, the break reduces the level of nesting
199 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800200
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800201 return QCBOR_SUCCESS;
202}
203
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700204// Called on every single item except breaks including decode of a map/array
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700205/* Decrements the map/array counter if possible. If decrement
206 closed out a map or array, then level up in nesting and decrement
207 again, until, the top is reached or the end of a map mode is reached
208 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800209inline static void
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700210DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800211{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700212 while(!DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700213 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800214
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800215 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700216 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800217 pNesting->pCurrent->uCount--;
218 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700219
220 if(pNesting->pCurrent->uCount != 0) {
221 // Did not close out an array or map, so nothing further
222 break;
223 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700224
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700225 if(pNesting->pCurrent->uMapMode) {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700226 // In map mode the level-up must be done explicitly
227 break;
228 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700229
230 // Closed out an array or map so level up
231 pNesting->pCurrent--;
232
233 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700234 }
235}
236
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700237inline static void
238DecodeNesting_EnterMapMode(QCBORDecodeNesting *pNesting, size_t uOffset)
239{
240 pNesting->pCurrent->uMapMode = 1;
241 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
242 pNesting->pCurrent->uOffset = (uint32_t)uOffset;
243}
244
245inline static void
246DecodeNesting_Exit(QCBORDecodeNesting *pNesting)
247{
248 pNesting->pCurrent->uMapMode = 0;
249 pNesting->pCurrent--;
250
251 DecodeNesting_DecrementCount(pNesting);
252}
253
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800254// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800255inline static QCBORError
256DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700257{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700258 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800259
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800260 if(pItem->val.uCount == 0) {
261 // Nothing to do for empty definite lenth arrays. They are just are
262 // effectively the same as an item that is not a map or array
263 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530264 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800265 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800266
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800267 // Error out if arrays is too long to handle
268 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700269 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
270 goto Done;
271 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800272
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800273 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700274 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
275 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
276 goto Done;
277 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800278
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800279 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700280 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800281
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800282 // Record a few details for this nesting level
283 pNesting->pCurrent->uMajorType = pItem->uDataType;
284 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700285 pNesting->pCurrent->uSaveCount = pItem->val.uCount;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700286 pNesting->pCurrent->uMapMode = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800287
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700288Done:
289 return nReturn;;
290}
291
Laurence Lundbladeee851742020-01-08 08:37:05 -0800292inline static void
293DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700294{
295 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
296}
297
298
299
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700300/*
301 This list of built-in tags. Only add tags here that are
302 clearly established and useful. Once a tag is added here
303 it can't be taken out as that would break backwards compatibility.
304 There are only 48 slots available forever.
305 */
306static const uint16_t spBuiltInTagMap[] = {
Laurence Lundblade59289e52019-12-30 13:44:37 -0800307 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
308 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
309 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
310 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
311 CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
312 CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700313 CBOR_TAG_COSE_ENCRYPTO,
314 CBOR_TAG_COSE_MAC0,
315 CBOR_TAG_COSE_SIGN1,
316 CBOR_TAG_ENC_AS_B64URL,
317 CBOR_TAG_ENC_AS_B64,
318 CBOR_TAG_ENC_AS_B16,
319 CBOR_TAG_CBOR,
320 CBOR_TAG_URI,
321 CBOR_TAG_B64URL,
322 CBOR_TAG_B64,
323 CBOR_TAG_REGEX,
324 CBOR_TAG_MIME,
325 CBOR_TAG_BIN_UUID,
326 CBOR_TAG_CWT,
327 CBOR_TAG_ENCRYPT,
328 CBOR_TAG_MAC,
329 CBOR_TAG_SIGN,
330 CBOR_TAG_GEO_COORD,
331 CBOR_TAG_CBOR_MAGIC
332};
333
334// This is used in a bit of cleverness in GetNext_TaggedItem() to
335// keep code size down and switch for the internal processing of
Laurence Lundblade59289e52019-12-30 13:44:37 -0800336// these types. This will break if the first six items in
337// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
338// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
339#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
340#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
341#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
342#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
343#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
344#define QCBOR_TAGFLAG_BIGFLOAT (0x01LL << CBOR_TAG_BIGFLOAT)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700345
Laurence Lundblade59289e52019-12-30 13:44:37 -0800346#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING |\
347 QCBOR_TAGFLAG_DATE_EPOCH |\
348 QCBOR_TAGFLAG_POS_BIGNUM |\
349 QCBOR_TAGFLAG_NEG_BIGNUM |\
350 QCBOR_TAGFLAG_DECIMAL_FRACTION |\
351 QCBOR_TAGFLAG_BIGFLOAT)
352
353#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
354 QCBOR_TAGFLAG_DATE_EPOCH |\
355 QCBOR_TAGFLAG_POS_BIGNUM |\
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700356 QCBOR_TAGFLAG_NEG_BIGNUM)
357
358#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
359#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
360#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
361
362static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
363{
364 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800365 /*
366 This is a cross-check to make sure the above array doesn't
367 accidentally get made too big. In normal conditions the above
368 test should optimize out as all the values are known at compile
369 time.
370 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700371 return -1;
372 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800373
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700374 if(uTag > UINT16_MAX) {
375 // This tag map works only on 16-bit tags
376 return -1;
377 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800378
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700379 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
380 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
381 return nTagBitIndex;
382 }
383 }
384 return -1; // Indicates no match
385}
386
387static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
388{
389 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
390 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
391 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
392 }
393 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800394
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700395 return -1; // Indicates no match
396}
397
398/*
399 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800400
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700401 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800402 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700403 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800404static QCBORError
405TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
406 uint64_t uTag,
407 uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700408{
409 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
410 if(nTagBitIndex >= 0) {
411 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
412 *puTagBitIndex = (uint8_t)nTagBitIndex;
413 return QCBOR_SUCCESS;
414 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800415
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700416 if(pCallerConfiguredTagMap) {
417 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
418 return QCBOR_ERR_TOO_MANY_TAGS;
419 }
420 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
421 if(nTagBitIndex >= 0) {
422 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
423
424 *puTagBitIndex = (uint8_t)nTagBitIndex;
425 return QCBOR_SUCCESS;
426 }
427 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800428
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700429 return QCBOR_ERR_BAD_OPT_TAG;
430}
431
432
433
Laurence Lundbladeee851742020-01-08 08:37:05 -0800434/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800435 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
436
437 The following four functions are pretty wrappers for invocation of
438 the string allocator supplied by the caller.
439
Laurence Lundbladeee851742020-01-08 08:37:05 -0800440 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800441
Laurence Lundbladeee851742020-01-08 08:37:05 -0800442static inline void
443StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800444{
445 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
446}
447
Laurence Lundbladeee851742020-01-08 08:37:05 -0800448// StringAllocator_Reallocate called with pMem NULL is
449// equal to StringAllocator_Allocate()
450static inline UsefulBuf
451StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
452 void *pMem,
453 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800454{
455 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
456}
457
Laurence Lundbladeee851742020-01-08 08:37:05 -0800458static inline UsefulBuf
459StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800460{
461 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
462}
463
Laurence Lundbladeee851742020-01-08 08:37:05 -0800464static inline void
465StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800466{
467 if(pMe->pfAllocator) {
468 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
469 }
470}
471
472
473
Laurence Lundbladeee851742020-01-08 08:37:05 -0800474/*===========================================================================
475 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700476
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800477 See qcbor/qcbor_decode.h for definition of the object
478 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800479 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700480/*
481 Public function, see header file
482 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800483void QCBORDecode_Init(QCBORDecodeContext *me,
484 UsefulBufC EncodedCBOR,
485 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700486{
487 memset(me, 0, sizeof(QCBORDecodeContext));
488 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800489 // Don't bother with error check on decode mode. If a bad value is
490 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700491 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700492 DecodeNesting_Init(&(me->nesting));
493}
494
495
496/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700497 Public function, see header file
498 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800499void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
500 QCBORStringAllocate pfAllocateFunction,
501 void *pAllocateContext,
502 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700503{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800504 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
505 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
506 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700507}
508
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800509
510/*
511 Public function, see header file
512 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800513void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
514 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700515{
516 me->pCallerConfiguredTagList = pTagList;
517}
518
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700519
520/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800521 This decodes the fundamental part of a CBOR data item, the type and
522 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800523
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700524 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800525
Laurence Lundbladeee851742020-01-08 08:37:05 -0800526 This does the network->host byte order conversion. The conversion
527 here also results in the conversion for floats in addition to that
528 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800529
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700530 This returns:
531 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800532
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800533 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800534 tags and floats and length for strings and arrays
535
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800536 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800537 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800538
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800539 The int type is preferred to uint8_t for some variables as this
540 avoids integer promotions, can reduce code size and makes
541 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700542 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800543inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
544 int *pnMajorType,
545 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800546 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700547{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700548 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800549
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700550 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800551 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800552
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700553 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800554 const int nTmpMajorType = nInitialByte >> 5;
555 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800556
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800557 // Where the number or argument accumulates
558 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800559
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800560 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800561 // Need to get 1,2,4 or 8 additional argument bytes Map
562 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800563 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800564
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800565 // Loop getting all the bytes in the argument
566 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800567 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800568 // This shift and add gives the endian conversion
569 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
570 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800571 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800572 // The reserved and thus-far unused additional info values
573 nReturn = QCBOR_ERR_UNSUPPORTED;
574 goto Done;
575 } else {
576 // Less than 24, additional info is argument or 31, an indefinite length
577 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800578 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700579 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800580
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700581 if(UsefulInputBuf_GetError(pUInBuf)) {
582 nReturn = QCBOR_ERR_HIT_END;
583 goto Done;
584 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800585
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700586 // All successful if we got here.
587 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800588 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800589 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800590 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800591
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700592Done:
593 return nReturn;
594}
595
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800596
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700597/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800598 CBOR doesn't explicitly specify two's compliment for integers but all
599 CPUs use it these days and the test vectors in the RFC are so. All
600 integers in the CBOR structure are positive and the major type
601 indicates positive or negative. CBOR can express positive integers
602 up to 2^x - 1 where x is the number of bits and negative integers
603 down to 2^x. Note that negative numbers can be one more away from
604 zero than positive. Stdint, as far as I can tell, uses two's
605 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800606
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700607 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800608 used carefully here, and in particular why it isn't used in the interface.
609 Also see
610 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
611
612 Int is used for values that need less than 16-bits and would be subject
613 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700614 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800615inline static QCBORError
616DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700617{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700618 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800619
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700620 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
621 if (uNumber <= INT64_MAX) {
622 pDecodedItem->val.int64 = (int64_t)uNumber;
623 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800624
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700625 } else {
626 pDecodedItem->val.uint64 = uNumber;
627 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800628
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700629 }
630 } else {
631 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800632 // CBOR's representation of negative numbers lines up with the
633 // two-compliment representation. A negative integer has one
634 // more in range than a positive integer. INT64_MIN is
635 // equal to (-INT64_MAX) - 1.
636 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700637 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800638
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639 } else {
640 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000641 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700642 nReturn = QCBOR_ERR_INT_OVERFLOW;
643 }
644 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800645
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646 return nReturn;
647}
648
649// Make sure #define value line up as DecodeSimple counts on this.
650#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
651#error QCBOR_TYPE_FALSE macro value wrong
652#endif
653
654#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
655#error QCBOR_TYPE_TRUE macro value wrong
656#endif
657
658#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
659#error QCBOR_TYPE_NULL macro value wrong
660#endif
661
662#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
663#error QCBOR_TYPE_UNDEF macro value wrong
664#endif
665
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700666#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
667#error QCBOR_TYPE_BREAK macro value wrong
668#endif
669
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700670#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
671#error QCBOR_TYPE_DOUBLE macro value wrong
672#endif
673
674#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
675#error QCBOR_TYPE_FLOAT macro value wrong
676#endif
677
678/*
679 Decode true, false, floats, break...
680 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800681inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800682DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700683{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700684 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800685
Laurence Lundbladeee851742020-01-08 08:37:05 -0800686 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800687 // above make sure uAdditionalInfo values line up with uDataType values.
688 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
689 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800690
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800691 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800692 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
693 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800694
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700695 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700696 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
697 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700698 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700699 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700700 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
701 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700702 break;
703 case DOUBLE_PREC_FLOAT:
704 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700705 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700706 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800707
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700708 case CBOR_SIMPLEV_FALSE: // 20
709 case CBOR_SIMPLEV_TRUE: // 21
710 case CBOR_SIMPLEV_NULL: // 22
711 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700712 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700713 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800714
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700715 case CBOR_SIMPLEV_ONEBYTE: // 24
716 if(uNumber <= CBOR_SIMPLE_BREAK) {
717 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700718 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700719 goto Done;
720 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800721 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800723
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724 default: // 0-19
725 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800726 /*
727 DecodeTypeAndNumber will make uNumber equal to
728 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
729 safe because the 2, 4 and 8 byte lengths of uNumber are in
730 the double/float cases above
731 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732 pDecodedItem->val.uSimple = (uint8_t)uNumber;
733 break;
734 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800735
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700736Done:
737 return nReturn;
738}
739
740
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700741/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530742 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700743 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800744inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
745 int nMajorType,
746 uint64_t uStrLen,
747 UsefulInputBuf *pUInBuf,
748 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700749{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700750 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800751
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800752 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
753 // This check makes the casts to size_t below safe.
754
755 // 4 bytes less than the largest sizeof() so this can be tested by
756 // putting a SIZE_MAX length in the CBOR test input (no one will
757 // care the limit on strings is 4 bytes shorter).
758 if(uStrLen > SIZE_MAX-4) {
759 nReturn = QCBOR_ERR_STRING_TOO_LONG;
760 goto Done;
761 }
762
763 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530764 if(UsefulBuf_IsNULLC(Bytes)) {
765 // Failed to get the bytes for this string item
766 nReturn = QCBOR_ERR_HIT_END;
767 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700768 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530769
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800770 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530771 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800772 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530773 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700774 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530775 goto Done;
776 }
777 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800778 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530779 } else {
780 // Normal case with no string allocator
781 pDecodedItem->val.string = Bytes;
782 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800783 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800784 // Cast because ternary operator causes promotion to integer
785 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
786 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800787
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530788Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700789 return nReturn;
790}
791
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700792
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800793
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700794
795
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700796
797
Laurence Lundbladeee851742020-01-08 08:37:05 -0800798// Make sure the constants align as this is assumed by
799// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700800#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
801#error QCBOR_TYPE_ARRAY value not lined up with major type
802#endif
803#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
804#error QCBOR_TYPE_MAP value not lined up with major type
805#endif
806
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700807/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800808 This gets a single data item and decodes it including preceding
809 optional tagging. This does not deal with arrays and maps and nesting
810 except to decode the data item introducing them. Arrays and maps are
811 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800812
Laurence Lundbladeee851742020-01-08 08:37:05 -0800813 Errors detected here include: an array that is too long to decode,
814 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700815 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800816static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
817 QCBORItem *pDecodedItem,
818 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700819{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700820 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800821
Laurence Lundbladeee851742020-01-08 08:37:05 -0800822 /*
823 Get the major type and the number. Number could be length of more
824 bytes or the value depending on the major type nAdditionalInfo is
825 an encoding of the length of the uNumber and is needed to decode
826 floats and doubles
827 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800828 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700829 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800830 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800831
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700832 memset(pDecodedItem, 0, sizeof(QCBORItem));
833
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800834 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800835
Laurence Lundbladeee851742020-01-08 08:37:05 -0800836 // Error out here if we got into trouble on the type and number. The
837 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700838 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700839 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700840 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800841
Laurence Lundbladeee851742020-01-08 08:37:05 -0800842 // At this point the major type and the value are valid. We've got
843 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800844 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700845 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
846 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800847 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700848 nReturn = QCBOR_ERR_BAD_INT;
849 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800850 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700851 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700852 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800853
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700854 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
855 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800856 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
857 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
858 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
859 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530860 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700861 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800862 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700863 }
864 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800865
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700866 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
867 case CBOR_MAJOR_TYPE_MAP: // Major type 5
868 // Record the number of items in the array or map
869 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
870 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
871 goto Done;
872 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800873 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530874 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700875 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800876 // type conversion OK because of check above
877 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700878 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800879 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800880 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
881 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700882 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800883
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700884 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800885 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700886 nReturn = QCBOR_ERR_BAD_INT;
887 } else {
888 pDecodedItem->val.uTagV = uNumber;
889 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
890 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700891 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800892
Laurence Lundbladeee851742020-01-08 08:37:05 -0800893 case CBOR_MAJOR_TYPE_SIMPLE:
894 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800895 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700896 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800897
Laurence Lundbladeee851742020-01-08 08:37:05 -0800898 default:
899 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700900 nReturn = QCBOR_ERR_UNSUPPORTED;
901 break;
902 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800903
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700904Done:
905 return nReturn;
906}
907
908
909
910/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800911 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800912 individual chunk items together into one QCBORItem using the string
913 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800914
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530915 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700916 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800917static inline QCBORError
918GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700919{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700920 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700921
922 // Get pointer to string allocator. First use is to pass it to
923 // GetNext_Item() when option is set to allocate for *every* string.
924 // Second use here is to allocate space to coallese indefinite
925 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800926 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
927 &(me->StringAllocator) :
928 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800929
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700930 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800931 nReturn = GetNext_Item(&(me->InBuf),
932 pDecodedItem,
933 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700934 if(nReturn) {
935 goto Done;
936 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800937
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700938 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530939 // code in this function from here down can be eliminated. Run tests, except
940 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800941
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800942 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700943 const uint8_t uStringType = pDecodedItem->uDataType;
944 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700945 goto Done; // no need to do any work here on non-string types
946 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800947
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800948 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530949 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800950 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700951 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800952
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530953 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800954 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700955 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
956 goto Done;
957 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800958
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700959 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700960 UsefulBufC FullString = NULLUsefulBufC;
961
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700962 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700963 // Get item for next chunk
964 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700965 // NULL string allocator passed here. Do not need to allocate
966 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800967 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700968 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700969 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700970 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800971
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530972 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700973 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800974 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700975 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530976 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700977 break;
978 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800979
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700980 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530981 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700982 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800983 if(StringChunkItem.uDataType != uStringType ||
984 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700985 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700986 break;
987 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800988
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530989 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800990 // The first time throurgh FullString.ptr is NULL and this is
991 // equivalent to StringAllocator_Allocate()
992 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
993 UNCONST_POINTER(FullString.ptr),
994 FullString.len + StringChunkItem.val.string.len);
995
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700996 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530997 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700998 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700999 break;
1000 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001001
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001002 // Copy new string chunk at the end of string so far.
1003 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001004 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001005
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001006 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1007 // Getting the item failed, clean up the allocated memory
1008 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001010
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001011Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001012 return nReturn;
1013}
1014
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001015
1016/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001017 Gets all optional tag data items preceding a data item that is not an
1018 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001019 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001020static QCBORError
1021GetNext_TaggedItem(QCBORDecodeContext *me,
1022 QCBORItem *pDecodedItem,
1023 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001024{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001025 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +07001026 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001027 uint64_t uTagBits = 0;
1028 if(pTags) {
1029 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001030 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001031
Laurence Lundblade59289e52019-12-30 13:44:37 -08001032 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001033 for(;;) {
1034 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001035 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001036 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001037 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001038
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001039 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1040 // Successful exit from loop; maybe got some tags, maybe not
1041 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001042 break;
1043 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001044
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001045 uint8_t uTagBitIndex;
1046 // Tag was mapped, tag was not mapped, error with tag list
1047 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001048
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001049 case QCBOR_SUCCESS:
1050 // Successfully mapped the tag
1051 uTagBits |= 0x01ULL << uTagBitIndex;
1052 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001053
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001054 case QCBOR_ERR_BAD_OPT_TAG:
1055 // Tag is not recognized. Do nothing
1056 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001057
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001058 default:
1059 // Error Condition
1060 goto Done;
1061 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001062
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001063 if(pTags) {
1064 // Caller wants all tags recorded in the provided buffer
1065 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1066 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
1067 goto Done;
1068 }
1069 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
1070 pTags->uNumUsed++;
1071 }
1072 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001073
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001074Done:
1075 return nReturn;
1076}
1077
1078
1079/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001080 This layer takes care of map entries. It combines the label and data
1081 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001082 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001083static inline QCBORError
1084GetNext_MapEntry(QCBORDecodeContext *me,
1085 QCBORItem *pDecodedItem,
1086 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001087{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001088 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +07001089 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001090 if(nReturn)
1091 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001092
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001093 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001094 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001095 goto Done;
1096 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001097
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001098 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1099 // In a map and caller wants maps decoded, not treated as arrays
1100
1101 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1102 // If in a map and the right decoding mode, get the label
1103
Laurence Lundbladeee851742020-01-08 08:37:05 -08001104 // Save label in pDecodedItem and get the next which will
1105 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001106 QCBORItem LabelItem = *pDecodedItem;
1107 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1108 if(nReturn)
1109 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001110
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301111 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001112
1113 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1114 // strings are always good labels
1115 pDecodedItem->label.string = LabelItem.val.string;
1116 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1117 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001118 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001119 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1120 goto Done;
1121 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1122 pDecodedItem->label.int64 = LabelItem.val.int64;
1123 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1124 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1125 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1126 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1127 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1128 pDecodedItem->label.string = LabelItem.val.string;
1129 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1130 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1131 } else {
1132 // label is not an int or a string. It is an arrray
1133 // or a float or such and this implementation doesn't handle that.
1134 // Also, tags on labels are ignored.
1135 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1136 goto Done;
1137 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001138 }
1139 } else {
1140 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001141 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1142 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1143 goto Done;
1144 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001145 // Decoding a map as an array
1146 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001147 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1148 // Cast is needed because of integer promotion
1149 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001150 }
1151 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001152
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001153Done:
1154 return nReturn;
1155}
1156
1157
1158/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001159 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001160 TODO: correct this comment
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001161 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001162QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
1163 QCBORItem *pDecodedItem,
1164 QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001165{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001166 // Stack ptr/int: 2, QCBORItem : 64
1167
Laurence Lundblade30816f22018-11-10 13:40:22 +07001168 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001169
Laurence Lundblade937ea812020-05-08 11:38:23 -07001170 /* For a pre-order traversal a non-error end occurs when there
1171 are no more bytes to consume and the nesting level is at the top.
1172 If it's not at the top, then the CBOR is not well formed. This error
1173 is caught elsewhere.
1174
1175 This handles the end of CBOR sequences as well as non-sequences. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001176 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001177 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1178 goto Done;
1179 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001180
1181 /* It is also and end of the input when in map mode and the cursor
1182 is at the end of the map */
1183
1184
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001185 // This is to handle map and array mode
Laurence Lundblade937ea812020-05-08 11:38:23 -07001186 if(DecodeNesting_AtEnd(&(me->nesting))) {
1187// if(UsefulInputBuf_Tell(&(me->InBuf)) != 0 && DecodeNesting_AtEnd(&(me->nesting))) {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001188 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1189 goto Done;
1190 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001191
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001192 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001193 if(nReturn) {
1194 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001195 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301196
1197 // Break ending arrays/maps are always processed at the end of this function.
1198 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301199 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301200 nReturn = QCBOR_ERR_BAD_BREAK;
1201 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301202 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001203
Laurence Lundblade6de37062018-10-15 12:22:42 +05301204 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301205 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301206 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001207
Laurence Lundblade6de37062018-10-15 12:22:42 +05301208 // Process the item just received for descent or decrement, and
1209 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001210 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001211 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001212 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001213 // Maps and arrays do count in as items in the map/array that encloses
1214 // them so a decrement needs to be done for them too, but that is done
1215 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001216 // are opened with the exception of an empty map or array.
1217 if(pDecodedItem->val.uCount == 0) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001218 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001219 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001220 } else {
1221 // Decrement the count of items in the enclosing map/array
1222 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301223 // triggers a decrement in the map/array above that and
1224 // an ascend in nesting level.
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001225 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001226 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301227 if(nReturn) {
1228 goto Done;
1229 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001230
Laurence Lundblade6de37062018-10-15 12:22:42 +05301231 // For indefinite length maps/arrays, looking at any and
1232 // all breaks that might terminate them. The equivalent
1233 // for definite length maps/arrays happens in
1234 // DecodeNesting_DecrementCount().
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001235 if(!DecodeNesting_IsAtTop(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301236 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1237 // Peek forward one item to see if it is a break.
1238 QCBORItem Peek;
1239 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1240 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1241 if(nReturn) {
1242 goto Done;
1243 }
1244 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1245 // It is not a break, rewind so it can be processed normally.
1246 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1247 break;
1248 }
1249 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301250 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301251 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1252 if(nReturn) {
1253 // break occured outside of an indefinite length array/map
1254 goto Done;
1255 }
1256 }
1257 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001258
Laurence Lundblade6de37062018-10-15 12:22:42 +05301259 // Tell the caller what level is next. This tells them what maps/arrays
1260 // were closed out and makes it possible for them to reconstruct
1261 // the tree with just the information returned by GetNext
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001262 if(me->nesting.pCurrent->uMapMode && me->nesting.pCurrent->uCount == 0) {
1263 // At end of a map / array in map mode, so next nest is 0 to
1264 // indicate this end.
1265 pDecodedItem->uNextNestLevel = 0;
1266 } else {
1267 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
1268 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001269
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001270Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001271 if(nReturn != QCBOR_SUCCESS) {
1272 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1273 memset(pDecodedItem, 0, sizeof(QCBORItem));
1274 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001275 return nReturn;
1276}
1277
1278
Laurence Lundblade59289e52019-12-30 13:44:37 -08001279/*
1280 Mostly just assign the right data type for the date string.
1281 */
1282inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1283{
1284 // Stack Use: UsefulBuf 1 16
1285 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1286 return QCBOR_ERR_BAD_OPT_TAG;
1287 }
1288
1289 const UsefulBufC Temp = pDecodedItem->val.string;
1290 pDecodedItem->val.dateString = Temp;
1291 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1292 return QCBOR_SUCCESS;
1293}
1294
1295
1296/*
1297 Mostly just assign the right data type for the bignum.
1298 */
1299inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1300{
1301 // Stack Use: UsefulBuf 1 -- 16
1302 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1303 return QCBOR_ERR_BAD_OPT_TAG;
1304 }
1305 const UsefulBufC Temp = pDecodedItem->val.string;
1306 pDecodedItem->val.bigNum = Temp;
Laurence Lundbladeee851742020-01-08 08:37:05 -08001307 const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001308 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1309 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001310 return QCBOR_SUCCESS;
1311}
1312
1313
1314/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001315 The epoch formatted date. Turns lots of different forms of encoding
1316 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001317 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001318static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001319{
1320 // Stack usage: 1
1321 QCBORError nReturn = QCBOR_SUCCESS;
1322
1323 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1324
1325 switch (pDecodedItem->uDataType) {
1326
1327 case QCBOR_TYPE_INT64:
1328 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1329 break;
1330
1331 case QCBOR_TYPE_UINT64:
1332 if(pDecodedItem->val.uint64 > INT64_MAX) {
1333 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1334 goto Done;
1335 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001336 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001337 break;
1338
1339 case QCBOR_TYPE_DOUBLE:
1340 {
1341 // This comparison needs to be done as a float before
1342 // conversion to an int64_t to be able to detect doubles
1343 // that are too large to fit into an int64_t. A double
1344 // has 52 bits of preceision. An int64_t has 63. Casting
1345 // INT64_MAX to a double actually causes a round up which
1346 // is bad and wrong for the comparison because it will
1347 // allow conversion of doubles that can't fit into a
1348 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1349 // the cutoff point as if that rounds up in conversion to
1350 // double it will still be less than INT64_MAX. 0x7ff is
1351 // picked because it has 11 bits set.
1352 //
1353 // INT64_MAX seconds is on the order of 10 billion years,
1354 // and the earth is less than 5 billion years old, so for
1355 // most uses this conversion error won't occur even though
1356 // doubles can go much larger.
1357 //
1358 // Without the 0x7ff there is a ~30 minute range of time
1359 // values 10 billion years in the past and in the future
1360 // where this this code would go wrong.
1361 const double d = pDecodedItem->val.dfnum;
1362 if(d > (double)(INT64_MAX - 0x7ff)) {
1363 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1364 goto Done;
1365 }
1366 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1367 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1368 }
1369 break;
1370
1371 default:
1372 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1373 goto Done;
1374 }
1375 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1376
1377Done:
1378 return nReturn;
1379}
1380
1381
1382#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1383/*
1384 Decode decimal fractions and big floats.
1385
1386 When called pDecodedItem must be the array that is tagged as a big
1387 float or decimal fraction, the array that has the two members, the
1388 exponent and mantissa.
1389
1390 This will fetch and decode the exponent and mantissa and put the
1391 result back into pDecodedItem.
1392 */
1393inline static QCBORError
1394QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1395{
1396 QCBORError nReturn;
1397
1398 // --- Make sure it is an array; track nesting level of members ---
1399 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1400 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1401 goto Done;
1402 }
1403
1404 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001405 // definite length arrays, but not for indefnite. Instead remember
1406 // the nesting level the two integers must be at, which is one
1407 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001408 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1409
1410 // --- Is it a decimal fraction or a bigfloat? ---
1411 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1412 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1413
1414 // --- Get the exponent ---
1415 QCBORItem exponentItem;
1416 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
1417 if(nReturn != QCBOR_SUCCESS) {
1418 goto Done;
1419 }
1420 if(exponentItem.uNestingLevel != nNestLevel) {
1421 // Array is empty or a map/array encountered when expecting an int
1422 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1423 goto Done;
1424 }
1425 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1426 // Data arriving as an unsigned int < INT64_MAX has been converted
1427 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1428 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1429 // will be too large for this to handle and thus an error that will
1430 // get handled in the next else.
1431 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1432 } else {
1433 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1434 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1435 goto Done;
1436 }
1437
1438 // --- Get the mantissa ---
1439 QCBORItem mantissaItem;
1440 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1441 if(nReturn != QCBOR_SUCCESS) {
1442 goto Done;
1443 }
1444 if(mantissaItem.uNestingLevel != nNestLevel) {
1445 // Mantissa missing or map/array encountered when expecting number
1446 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1447 goto Done;
1448 }
1449 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1450 // Data arriving as an unsigned int < INT64_MAX has been converted
1451 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1452 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1453 // will be too large for this to handle and thus an error that
1454 // will get handled in an else below.
1455 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1456 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1457 // Got a good big num mantissa
1458 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1459 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001460 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1461 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1462 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001463 } else {
1464 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1465 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1466 goto Done;
1467 }
1468
1469 // --- Check that array only has the two numbers ---
1470 if(mantissaItem.uNextNestLevel == nNestLevel) {
1471 // Extra items in the decimal fraction / big num
1472 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1473 goto Done;
1474 }
1475
1476Done:
1477
1478 return nReturn;
1479}
1480#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1481
1482
1483/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001484 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001485 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001486QCBORError
1487QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1488 QCBORItem *pDecodedItem,
1489 QCBORTagListOut *pTags)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001490{
1491 QCBORError nReturn;
1492
1493 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
1494 if(nReturn != QCBOR_SUCCESS) {
1495 goto Done;
1496 }
1497
1498#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1499#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
1500#else
1501#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
1502#endif
1503
1504 // Only pay attention to tags this code knows how to decode.
1505 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
1506 case 0:
1507 // No tags at all or none we know about. Nothing to do.
1508 // This is the pass-through path of this function
1509 // that will mostly be taken when decoding any item.
1510 break;
1511
1512 case QCBOR_TAGFLAG_DATE_STRING:
1513 nReturn = DecodeDateString(pDecodedItem);
1514 break;
1515
1516 case QCBOR_TAGFLAG_DATE_EPOCH:
1517 nReturn = DecodeDateEpoch(pDecodedItem);
1518 break;
1519
1520 case QCBOR_TAGFLAG_POS_BIGNUM:
1521 case QCBOR_TAGFLAG_NEG_BIGNUM:
1522 nReturn = DecodeBigNum(pDecodedItem);
1523 break;
1524
1525#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1526 case QCBOR_TAGFLAG_DECIMAL_FRACTION:
1527 case QCBOR_TAGFLAG_BIGFLOAT:
1528 // For aggregate tagged types, what goes into pTags is only collected
1529 // from the surrounding data item, not the contents, so pTags is not
1530 // passed on here.
1531
1532 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1533 break;
1534#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1535
1536 default:
1537 // Encountering some mixed-up CBOR like something that
1538 // is tagged as both a string and integer date.
1539 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1540 }
1541
1542Done:
1543 if(nReturn != QCBOR_SUCCESS) {
1544 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1545 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1546 }
1547 return nReturn;
1548}
1549
1550
1551/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001552 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001553 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001554QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001555{
1556 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1557}
1558
1559
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001560/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301561 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301562 next one down. If a layer has no work to do for a particular item
1563 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001564
Laurence Lundblade59289e52019-12-30 13:44:37 -08001565 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1566 tagged data items, turning them into the local C representation.
1567 For the most simple it is just associating a QCBOR_TYPE with the data. For
1568 the complex ones that an aggregate of data items, there is some further
1569 decoding and a little bit of recursion.
1570
1571 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301572 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301573 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001574 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001575
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301576 - GetNext_MapEntry -- This handles the combining of two
1577 items, the label and the data, that make up a map entry.
1578 It only does work on maps. It combines the label and data
1579 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001580
Laurence Lundblade59289e52019-12-30 13:44:37 -08001581 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1582 tags into bit flags associated with the data item. No actual decoding
1583 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001584
Laurence Lundblade59289e52019-12-30 13:44:37 -08001585 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301586 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301587 string allocater to create contiguous space for the item. It
1588 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001589
Laurence Lundblade59289e52019-12-30 13:44:37 -08001590 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1591 atomic data item has a "major type", an integer "argument" and optionally
1592 some content. For text and byte strings, the content is the bytes
1593 that make up the string. These are the smallest data items that are
1594 considered to be well-formed. The content may also be other data items in
1595 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001596
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001597 Roughly this takes 300 bytes of stack for vars. Need to
1598 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001599
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301600 */
1601
1602
1603/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001604 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001605 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001606int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1607 const QCBORItem *pItem,
1608 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001609{
1610 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001611
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001612 uint8_t uTagBitIndex;
1613 // Do not care about errors in pCallerConfiguredTagMap here. They are
1614 // caught during GetNext() before this is called.
1615 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1616 return 0;
1617 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001618
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001619 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1620 return (uTagBit & pItem->uTagBits) != 0;
1621}
1622
1623
1624/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001625 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001626 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001627QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001628{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001629 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001630
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001631 // Error out if all the maps/arrays are not closed out
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001632 if(!DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001633 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1634 goto Done;
1635 }
1636
1637 // Error out if not all the bytes are consumed
1638 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1639 nReturn = QCBOR_ERR_EXTRA_BYTES;
1640 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001641
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001642Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301643 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001644 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001645 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001646
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001647 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001648}
1649
1650
1651
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001652/*
1653
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001654Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001655
Laurence Lundbladeee851742020-01-08 08:37:05 -08001656 - Hit end of input before it was expected while decoding type and
1657 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001658
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001659 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001660
Laurence Lundbladeee851742020-01-08 08:37:05 -08001661 - Hit end of input while decoding a text or byte string
1662 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001663
Laurence Lundbladeee851742020-01-08 08:37:05 -08001664 - Encountered conflicting tags -- e.g., an item is tagged both a date
1665 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001666
Laurence Lundbladeee851742020-01-08 08:37:05 -08001667 - Encontered an array or mapp that has too many items
1668 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001669
Laurence Lundbladeee851742020-01-08 08:37:05 -08001670 - Encountered array/map nesting that is too deep
1671 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001672
Laurence Lundbladeee851742020-01-08 08:37:05 -08001673 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1674 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001675
Laurence Lundbladeee851742020-01-08 08:37:05 -08001676 - The type of a map label is not a string or int
1677 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001678
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001679 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001680
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001681 */
1682
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001683
1684
Laurence Lundbladef6531662018-12-04 10:42:22 +09001685
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001686/* ===========================================================================
1687 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001688
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001689 This implements a simple sting allocator for indefinite length
1690 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1691 implements the function type QCBORStringAllocate and allows easy
1692 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001693
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001694 This particular allocator is built-in for convenience. The caller
1695 can implement their own. All of this following code will get
1696 dead-stripped if QCBORDecode_SetMemPool() is not called.
1697
1698 This is a very primitive memory allocator. It does not track
1699 individual allocations, only a high-water mark. A free or
1700 reallocation must be of the last chunk allocated.
1701
1702 The size of the pool and offset to free memory are packed into the
1703 first 8 bytes of the memory pool so we don't have to keep them in
1704 the decode context. Since the address of the pool may not be
1705 aligned, they have to be packed and unpacked as if they were
1706 serialized data of the wire or such.
1707
1708 The sizes packed in are uint32_t to be the same on all CPU types
1709 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001710 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001711
1712
Laurence Lundbladeee851742020-01-08 08:37:05 -08001713static inline int
1714MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001715{
1716 // Use of UsefulInputBuf is overkill, but it is convenient.
1717 UsefulInputBuf UIB;
1718
Laurence Lundbladeee851742020-01-08 08:37:05 -08001719 // Just assume the size here. It was checked during SetUp so
1720 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001721 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1722 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1723 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1724 return UsefulInputBuf_GetError(&UIB);
1725}
1726
1727
Laurence Lundbladeee851742020-01-08 08:37:05 -08001728static inline int
1729MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001730{
1731 // Use of UsefulOutBuf is overkill, but convenient. The
1732 // length check performed here is useful.
1733 UsefulOutBuf UOB;
1734
1735 UsefulOutBuf_Init(&UOB, Pool);
1736 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1737 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1738 return UsefulOutBuf_GetError(&UOB);
1739}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001740
1741
1742/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001743 Internal function for an allocation, reallocation free and destuct.
1744
1745 Having only one function rather than one each per mode saves space in
1746 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001747
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001748 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1749 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001750static UsefulBuf
1751MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001752{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001753 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001754
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001755 uint32_t uPoolSize;
1756 uint32_t uFreeOffset;
1757
1758 if(uNewSize > UINT32_MAX) {
1759 // This allocator is only good up to 4GB. This check should
1760 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1761 goto Done;
1762 }
1763 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1764
1765 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1766 goto Done;
1767 }
1768
1769 if(uNewSize) {
1770 if(pMem) {
1771 // REALLOCATION MODE
1772 // Calculate pointer to the end of the memory pool. It is
1773 // assumed that pPool + uPoolSize won't wrap around by
1774 // assuming the caller won't pass a pool buffer in that is
1775 // not in legitimate memory space.
1776 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1777
1778 // Check that the pointer for reallocation is in the range of the
1779 // pool. This also makes sure that pointer math further down
1780 // doesn't wrap under or over.
1781 if(pMem >= pPool && pMem < pPoolEnd) {
1782 // Offset to start of chunk for reallocation. This won't
1783 // wrap under because of check that pMem >= pPool. Cast
1784 // is safe because the pool is always less than UINT32_MAX
1785 // because of check in QCBORDecode_SetMemPool().
1786 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1787
1788 // Check to see if the allocation will fit. uPoolSize -
1789 // uMemOffset will not wrap under because of check that
1790 // pMem is in the range of the uPoolSize by check above.
1791 if(uNewSize <= uPoolSize - uMemOffset) {
1792 ReturnValue.ptr = pMem;
1793 ReturnValue.len = uNewSize;
1794
1795 // Addition won't wrap around over because uNewSize was
1796 // checked to be sure it is less than the pool size.
1797 uFreeOffset = uMemOffset + uNewSize32;
1798 }
1799 }
1800 } else {
1801 // ALLOCATION MODE
1802 // uPoolSize - uFreeOffset will not underflow because this
1803 // pool implementation makes sure uFreeOffset is always
1804 // smaller than uPoolSize through this check here and
1805 // reallocation case.
1806 if(uNewSize <= uPoolSize - uFreeOffset) {
1807 ReturnValue.len = uNewSize;
1808 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001809 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001810 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001811 }
1812 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001813 if(pMem) {
1814 // FREE MODE
1815 // Cast is safe because of limit on pool size in
1816 // QCBORDecode_SetMemPool()
1817 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1818 } else {
1819 // DESTRUCT MODE
1820 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001821 }
1822 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001823
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001824 UsefulBuf Pool = {pPool, uPoolSize};
1825 MemPool_Pack(Pool, uFreeOffset);
1826
1827Done:
1828 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001829}
1830
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001831
Laurence Lundbladef6531662018-12-04 10:42:22 +09001832/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001833 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09001834 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001835QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1836 UsefulBuf Pool,
1837 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001838{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001839 // The pool size and free mem offset are packed into the beginning
1840 // of the pool memory. This compile time check make sure the
1841 // constant in the header is correct. This check should optimize
1842 // down to nothing.
1843 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001844 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001845 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001846
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001847 // The pool size and free offset packed in to the beginning of pool
1848 // memory are only 32-bits. This check will optimize out on 32-bit
1849 // machines.
1850 if(Pool.len > UINT32_MAX) {
1851 return QCBOR_ERR_BUFFER_TOO_LARGE;
1852 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001853
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001854 // This checks that the pool buffer given is big enough.
1855 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1856 return QCBOR_ERR_BUFFER_TOO_SMALL;
1857 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001858
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001859 pMe->StringAllocator.pfAllocator = MemPool_Function;
1860 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1861 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001862
Laurence Lundblade30816f22018-11-10 13:40:22 +07001863 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001864}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001865
Laurence Lundblade1341c592020-04-11 14:19:05 -07001866#include <stdio.h>
1867void printdecode(QCBORDecodeContext *pMe, const char *szName)
1868{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001869 printf("---%s--%d--%d--\nLevel Count Type Offset SaveCount MapMode\n",
1870 szName,
1871 (uint32_t)pMe->InBuf.cursor,
1872 (uint32_t)pMe->InBuf.UB.len);
1873/* for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
1874 if(&(pMe->nesting.pMapsAndArrays[i]) > pMe->nesting.pCurrent) {
1875 break;
1876 }
1877 printf(" %2d %5d %s %6u %2d %d\n",
Laurence Lundblade1341c592020-04-11 14:19:05 -07001878 i,
1879 pMe->nesting.pMapsAndArrays[i].uCount,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001880 pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_MAP ? " map" :
1881 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_ARRAY ? "array" :
1882 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_NONE ? " none" : "?????")),
Laurence Lundblade1341c592020-04-11 14:19:05 -07001883 pMe->nesting.pMapsAndArrays[i].uOffset,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001884 pMe->nesting.pMapsAndArrays[i].uSaveCount,
1885 pMe->nesting.pMapsAndArrays[i].uMapMode
Laurence Lundblade1341c592020-04-11 14:19:05 -07001886 );
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001887
Laurence Lundblade1341c592020-04-11 14:19:05 -07001888 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001889 printf("\n"); */
Laurence Lundblade1341c592020-04-11 14:19:05 -07001890}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001891
1892
1893/*
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001894 *
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001895 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001896static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001897ConsumeItem(QCBORDecodeContext *pMe,
1898 const QCBORItem *pItemToConsume,
1899 uint_fast8_t *puNextNestLevel)
1900{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001901 QCBORError nReturn;
1902 QCBORItem Item;
1903
1904 printdecode(pMe, "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001905
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001906 if(IsMapOrArray(pItemToConsume->uDataType)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001907 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001908
Laurence Lundblade1341c592020-04-11 14:19:05 -07001909 /* This works for definite and indefinite length
1910 * maps and arrays by using the nesting level
1911 */
1912 do {
1913 nReturn = QCBORDecode_GetNext(pMe, &Item);
1914 if(nReturn != QCBOR_SUCCESS) {
1915 goto Done;
1916 }
1917 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001918
Laurence Lundblade1341c592020-04-11 14:19:05 -07001919 if(puNextNestLevel != NULL) {
1920 *puNextNestLevel = Item.uNextNestLevel;
1921 }
1922 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001923
Laurence Lundblade1341c592020-04-11 14:19:05 -07001924 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001925 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07001926 if(puNextNestLevel != NULL) {
1927 /* Just pass the nesting level through */
1928 *puNextNestLevel = pItemToConsume->uNextNestLevel;
1929 }
1930 nReturn = QCBOR_SUCCESS;
1931 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001932
1933Done:
1934 return nReturn;
1935}
1936
1937
Laurence Lundblade1341c592020-04-11 14:19:05 -07001938/* Return true if the labels in Item1 and Item2 are the same.
1939 Works only for integer and string labels. Returns false
1940 for any other type. */
1941static inline bool
1942MatchLabel(QCBORItem Item1, QCBORItem Item2)
1943{
1944 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
1945 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
1946 return true;
1947 }
1948 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001949 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001950 return true;
1951 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001952 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07001953 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
1954 return true;
1955 }
1956 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
1957 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
1958 return true;
1959 }
1960 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001961
Laurence Lundblade1341c592020-04-11 14:19:05 -07001962 /* Other label types are never matched */
1963 return false;
1964}
1965
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001966static inline bool
1967MatchType(QCBORItem Item1, QCBORItem Item2)
1968{
1969 if(Item1.uDataType == Item2.uDataType) {
1970 return true;
1971 } else if(Item1.uLabelType == QCBOR_TYPE_ANY) {
1972 return true;
1973 } else if(Item2.uLabelType == QCBOR_TYPE_ANY) {
1974 return true;
1975 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001976 return false;
1977}
1978
1979
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001980/*
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001981 On input pItemArray contains a list of labels and data types
1982 of items to be found.
1983
1984 On output the fully retrieved items are filled in with
1985 values and such. The label was matched, so it never changes.
1986
1987 If an item was not found, its data type is set to none.
1988
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001989 */
1990QCBORError
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001991GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemArray, size_t *puOffset, size_t *puEndOffset)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001992{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001993 QCBORError nReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07001994
1995 // 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 -07001996 if(!DecodeNesting_InMapMode(&(pMe->nesting))) {
1997 return QCBOR_ERR_NOT_ENTERED;
Laurence Lundblade1341c592020-04-11 14:19:05 -07001998 }
1999
Laurence Lundblade1341c592020-04-11 14:19:05 -07002000 QCBORDecodeNesting N = pMe->nesting;
2001
2002 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
2003 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2004 }
2005
2006 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2007
2008 /* Loop over all the items in the map. They could be
2009 * deeply nested and this should handle both definite
2010 * and indefinite length maps and arrays, so this
2011 * adds some complexity. */
2012 const uint8_t uMapNestLevel = DecodeNesting_GetLevel(&(pMe->nesting));
2013
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002014 uint_fast8_t uNextNestLevel;
2015
2016 uint64_t uFound = 0;
2017
2018 do {
2019 /* Remember offset because sometims we have to return it */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002020 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002021
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002022 /* Get the item */
2023 QCBORItem Item;
2024 nReturn = QCBORDecode_GetNext(pMe, &Item);
2025 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002026 /* Got non-well-formed CBOR */
2027 goto Done;
2028 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002029
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002030 /* See if item has one of the labels that are of interest */
2031 int i;
2032 QCBORItem *pIterator;
2033 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002034 if(MatchLabel(Item, *pIterator)) {
2035 // A label match has been found
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002036 if(uFound & (0x01ULL << i)) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002037 nReturn = QCBOR_ERR_DUPLICATE_LABEL;
2038 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002039 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002040 if(!MatchType(Item, *pIterator)) {
2041 nReturn = QCBOR_ERR_UNEXPECTED_TYPE;
2042 goto Done;
2043 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002044
2045 /* Successful match. Return the item. */
2046 *pIterator = Item;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002047 uFound |= 0x01ULL << i;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002048 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002049 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002050 }
2051 }
2052 }
2053
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002054 /* Consume the item whether matched or not. This
2055 does th work of traversing maps and array and
2056 everything in them. In this loop only the
2057 items at the current nesting level are examined
2058 to match the labels. */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002059 nReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2060 if(nReturn) {
2061 goto Done;
2062 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002063
2064 } while (uNextNestLevel >= uMapNestLevel);
2065
2066
2067 nReturn = QCBOR_SUCCESS;
2068
2069 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
2070 // Cast OK because encoded CBOR is limited to UINT32_MAX
2071 pMe->uMapEndOffset = (uint32_t)uEndOffset;
2072 // TODO: is zero *puOffset OK?
2073 if(puEndOffset) {
2074 *puEndOffset = uEndOffset;
2075 }
2076
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002077 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002078 int i;
2079 QCBORItem *pIterator;
2080 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
2081 if(!(uFound & (0x01ULL << i))) {
2082 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002083 }
2084 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002085
2086Done:
Laurence Lundblade1341c592020-04-11 14:19:05 -07002087 pMe->nesting = N;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002088
Laurence Lundblade1341c592020-04-11 14:19:05 -07002089 return nReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002090}
2091
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002092
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002093void QCBORDecode_ExitMap(QCBORDecodeContext *pMe)
2094{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002095 size_t uEndOffset;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002096
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002097/*
Laurence Lundblade1341c592020-04-11 14:19:05 -07002098 if(pMe->uMapEndOffset) {
2099 uEndOffset = pMe->uMapEndOffset;
2100 // It is only valid once.
2101 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002102 } else { */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002103 QCBORItem Dummy;
2104
2105 Dummy.uLabelType = QCBOR_TYPE_NONE;
2106
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002107 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002108
2109 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002110// }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002111
2112 printdecode(pMe, "start exit");
2113 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2114
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002115 DecodeNesting_Exit(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002116 printdecode(pMe, "end exit");
2117
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002118}
2119
2120
2121QCBORError QCBORDecode_GetItemInMap(QCBORDecodeContext *pMe,
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002122 int64_t nLabel,
2123 uint8_t uQcborType,
2124 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002125{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002126 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002127
Laurence Lundblade1341c592020-04-11 14:19:05 -07002128 One[0].uLabelType = QCBOR_TYPE_INT64;
2129 One[0].label.int64 = nLabel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002130 One[0].uDataType = uQcborType;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002131 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2132
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002133 QCBORError nReturn = GetItemsInMap(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002134 if(nReturn) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002135 return nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002136 }
2137
2138 if(One[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002139 return QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002140 }
2141
2142 *pItem = One[0];
2143
2144 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002145}
2146
2147
2148QCBORError QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002149 const char *szLabel,
2150 uint8_t uQcborType,
2151 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002152{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002153 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002154
Laurence Lundblade1341c592020-04-11 14:19:05 -07002155 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2156 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002157 One[0].uDataType = uQcborType;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002158 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2159
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002160 QCBORError nReturn = GetItemsInMap(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002161 if(nReturn) {
2162 return nReturn;
2163 }
2164
2165 if(One[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002166 return QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002167 }
2168
2169 *pItem = One[0];
2170
2171 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002172}
2173
2174
Laurence Lundblade1341c592020-04-11 14:19:05 -07002175
Laurence Lundblade1341c592020-04-11 14:19:05 -07002176
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002177static int FinishEnter(QCBORDecodeContext *pMe, size_t uOffset)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002178{
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002179 /* Seek to the data item that is the map or array */
2180 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2181
2182 /* Skip the data item that is the map or array */
2183 QCBORItem MapToEnter;
2184 // TODO: check error
2185 QCBORDecode_GetNext(pMe, &MapToEnter);
2186
2187 /* Enter map mode with an offset that is the first item
2188 in the map or array. */
2189 // TODO: what if map or array is empty?
2190 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
2191
2192
2193 printdecode(pMe, "Entered Map in Map");
2194
2195 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002196}
2197
2198
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002199QCBORError QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002200{
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002201 /* Use GetItemsInMap to find the map by label, including the
2202 byte offset of it. */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002203 QCBORItem One[2];
Laurence Lundblade1341c592020-04-11 14:19:05 -07002204 One[0].uLabelType = QCBOR_TYPE_INT64;
2205 One[0].label.int64 = nLabel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002206 One[0].uDataType = QCBOR_TYPE_MAP;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002207 One[1].uLabelType = QCBOR_TYPE_NONE;
2208
2209 size_t uOffset;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002210 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002211 if(nReturn) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002212 return nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002213 }
2214
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002215 /* The map to enter was found, now finish of entering it. */
2216 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002217
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002218 // TODO: error code?
Laurence Lundblade1341c592020-04-11 14:19:05 -07002219 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002220}
2221
2222
2223QCBORError QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2224{
2225 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002226
Laurence Lundblade1341c592020-04-11 14:19:05 -07002227 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2228 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002229 One[0].uDataType = QCBOR_TYPE_MAP;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002230 One[1].uLabelType = QCBOR_TYPE_NONE;
2231
2232 size_t uOffset;
2233
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002234 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002235
2236 if(nReturn) {
2237 return nReturn;
2238 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002239
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002240 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002241
2242 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002243}
2244
2245
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002246QCBORError QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002247{
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002248 QCBORItem One[2];
2249
2250 One[0].uLabelType = QCBOR_TYPE_INT64;
2251 One[0].label.int64 = nLabel;
2252 One[0].uDataType = QCBOR_TYPE_ARRAY;
2253 One[1].uLabelType = QCBOR_TYPE_NONE;
2254
2255 size_t uOffset;
2256
2257 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
2258
2259 if(nReturn != QCBOR_SUCCESS) {
2260 return nReturn;
2261 }
2262
2263 FinishEnter(pMe, uOffset);
2264
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002265 return 0;
2266}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002267
Laurence Lundblade1341c592020-04-11 14:19:05 -07002268
2269QCBORError QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2270{
2271 QCBORItem One[2];
2272
2273 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2274 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002275 One[0].uDataType = QCBOR_TYPE_ARRAY;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002276 One[1].uLabelType = QCBOR_TYPE_NONE;
2277
2278 size_t uOffset;
2279
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002280 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002281
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002282 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002283 return nReturn;
2284 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002285
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002286 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002287
2288 return 0;
2289}
2290
2291
2292
2293
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002294
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002295/* Next item must be map or this generates an error */
2296QCBORError QCBORDecode_EnterMap(QCBORDecodeContext *pMe)
2297{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002298 QCBORItem Item;
2299 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002300
2301 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002302 nReturn = QCBORDecode_GetNext(pMe, &Item);
2303 if(nReturn != QCBOR_SUCCESS) {
2304 return nReturn;
2305 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002306 if(Item.uDataType != QCBOR_TYPE_MAP) {
2307 return QCBOR_ERR_UNEXPECTED_TYPE;
2308 }
2309
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002310 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002311
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002312 printdecode(pMe, "EnterMapDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002313
Laurence Lundblade1341c592020-04-11 14:19:05 -07002314 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002315}
2316
2317
2318
2319QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2320{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002321 return GetItemsInMap(pCtx, pItemList, NULL, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002322}
2323
2324
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002325
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002326
2327
Laurence Lundblade1341c592020-04-11 14:19:05 -07002328void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002329{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002330 // TODO: check for map mode
2331 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2332 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2333}
2334
2335
2336QCBORError QCBORDecode_EnterArray(QCBORDecodeContext *pMe)
2337{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002338 QCBORItem Item;
2339 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002340
2341 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002342 nReturn = QCBORDecode_GetNext(pMe, &Item);
2343 if(nReturn != QCBOR_SUCCESS) {
2344 return nReturn;
2345 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002346 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
2347 return QCBOR_ERR_UNEXPECTED_TYPE;
2348 }
2349
2350 printdecode(pMe, "EnterArray");
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002351
2352 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002353
2354 return QCBOR_SUCCESS;
2355}
2356
2357
2358void QCBORDecode_ExitArray(QCBORDecodeContext *pMe)
2359{
2360 // TODO: make sure we have entered an array
2361 // TODO: combine with code for map? It is the same so far.
2362 size_t uEndOffset;
2363
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002364 /* if(pMe->uMapEndOffset) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002365 uEndOffset = pMe->uMapEndOffset;
2366 // It is only valid once.
2367 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002368 } else {*/
Laurence Lundblade1341c592020-04-11 14:19:05 -07002369 QCBORItem Dummy;
2370
2371 Dummy.uLabelType = QCBOR_TYPE_NONE;
2372
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002373 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002374
2375 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002376 //}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002377
Laurence Lundblade1341c592020-04-11 14:19:05 -07002378 printdecode(pMe, "start exit");
2379 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2380
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002381 DecodeNesting_Exit(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002382 printdecode(pMe, "end exit");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002383}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002384
Laurence Lundbladee6430642020-03-14 21:15:44 -07002385
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002386void QCBORDecode_GetIntInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, int64_t *pInt)
2387{
2388 // TODO: error handling
2389 QCBORItem Item;
2390 QCBORDecode_GetItemInMapSZ(pMe,szLabel, QCBOR_TYPE_INT64, &Item);
2391 *pInt = Item.val.int64;
2392}
2393
2394void QCBORDecode_GetBstrInMapN(QCBORDecodeContext *pMe, int64_t nLabel, UsefulBufC *pBstr)
2395{
2396 // TODO: error handling
2397 QCBORItem Item;
2398 QCBORDecode_GetItemInMap(pMe, nLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2399 *pBstr = Item.val.string;
2400}
2401
2402void QCBORDecode_GetBstrInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2403{
2404 // TODO: error handling
2405 QCBORItem Item;
2406 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2407 *pBstr = Item.val.string;
2408}
2409
Laurence Lundblade11a064e2020-05-07 13:13:42 -07002410void QCBORDecode_GetDateStringInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2411{
2412 // TODO: error handling
2413 QCBORItem Item;
2414 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_DATE_STRING, &Item);
2415 *pBstr = Item.val.string;
2416}
2417
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002418void QCBORDecode_GetTextInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2419{
2420 // TODO: error handling
2421 QCBORItem Item;
2422 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_TEXT_STRING, &Item);
2423 *pBstr = Item.val.string;
2424}
2425
Laurence Lundbladee6430642020-03-14 21:15:44 -07002426
Laurence Lundbladec4537442020-04-14 18:53:22 -07002427void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002428{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002429 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002430 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07002431 return;
2432 }
2433
Laurence Lundbladec4537442020-04-14 18:53:22 -07002434 QCBORError nError;
2435 QCBORItem Item;
2436
2437 nError = QCBORDecode_GetNext(pMe, &Item);
2438 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002439 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002440 return;
2441 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002442
2443 switch(Item.uDataType) {
2444 case QCBOR_TYPE_TRUE:
2445 *pValue = true;
2446 break;
2447
2448 case QCBOR_TYPE_FALSE:
2449 *pValue = false;
2450 break;
2451
2452 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002453 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002454 break;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002455 }
2456}
2457
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002458#if 0
2459// TODO: fix this
Laurence Lundbladee6430642020-03-14 21:15:44 -07002460/* Types of text strings
2461 * Plain, b64, b64url, URI, regex, MIME Text
2462 * One function for each with options to expect plain?
2463 * One function for all so you can say what you want?
Laurence Lundbladec4537442020-04-14 18:53:22 -07002464 *
2465 * A label is expected if pLabel is not NULL.
Laurence Lundbladee6430642020-03-14 21:15:44 -07002466 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002467void QCBORDecode_GetTextFoo(QCBORDecodeContext *pMe, QCBORLabel *pLabel, UsefulBufC *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002468{
2469 QCBORItem Item;
2470 QCBORError nError;
2471
2472 nError = QCBORDecode_GetNext(pMe, &Item);
2473 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002474 pMe->uLastError = nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002475 return;
2476 }
2477
Laurence Lundbladec4537442020-04-14 18:53:22 -07002478 if(pLabel != NULL) {
2479 if(Item.uLabelType == QCBOR_TYPE_NONE) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002480 pMe->uLastError = 9; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07002481 return;
2482 } else {
2483 // TODO: what about label allocation?
2484 pLabel->uLabelType = Item.uLabelType;
2485 pLabel->label.xx = Item.label.int64; // TOOD: figure out assignment
2486 }
2487 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002488
2489 switch(Item.uDataType) {
2490 case QCBOR_TYPE_TEXT_STRING:
2491 *pValue = Item.val.string;
2492 break;
2493
2494 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002495 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002496 }
2497}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002498#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002499
2500
Laurence Lundbladec4537442020-04-14 18:53:22 -07002501/*
2502 Options for MIME data, CBOR, positive big num, negative big num ??
2503 */
2504void QCBORDecode_GetStringInternal(QCBORDecodeContext *pMe, UsefulBufC *pValue, uint8_t uType)
2505{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002506 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002507 // Already in error state, do nothing
2508 return;
2509 }
2510
2511 QCBORError nError;
2512 QCBORItem Item;
2513
2514 nError = QCBORDecode_GetNext(pMe, &Item);
2515 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002516 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002517 return;
2518 }
2519
2520 if(Item.uDataType == uType) {
2521 *pValue = Item.val.string;
2522 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002523 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002524 }
2525}
2526
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002527void QCBORDecode_GetBytes(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002528{
2529 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_BYTE_STRING);
2530}
2531
2532
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002533void QCBORDecode_GetText(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002534{
2535 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_TEXT_STRING);
2536}
2537
2538
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002539void QCBORDecode_GetPosBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002540{
2541 // TODO: do these have to be tagged?
2542 // Probably should allow tagged or untagged, but not wrong-tagged
2543 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_POSBIGNUM);
2544}
2545
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002546void QCBORDecode_GetNegBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002547{
2548 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_NEGBIGNUM);
2549}
2550
2551
2552
Laurence Lundbladee6430642020-03-14 21:15:44 -07002553
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002554typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002555
2556
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002557// The main exponentiator that works on only positive numbers
2558static QCBORError Exponentitate10UU(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002559{
2560 uint64_t uResult;
2561
2562 uResult = uMantissa;
2563
2564 /* This loop will run a maximum of 19 times because
2565 * UINT64_MAX < 10 ^^ 19. More than that will cause
2566 * exit with the overflow error
2567 */
2568 while(nExponent > 0) {
2569 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002570 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladec4537442020-04-14 18:53:22 -07002571 }
2572 uResult = uResult * 10;
2573 nExponent--;
2574 }
2575
2576 while(nExponent < 0 ) {
2577 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002578 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
Laurence Lundbladec4537442020-04-14 18:53:22 -07002579 }
2580 uResult = uResult / 10;
2581 nExponent--;
2582 }
2583
2584 *puResult = uResult;
2585
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002586 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002587}
2588
2589
Laurence Lundbladee6430642020-03-14 21:15:44 -07002590/* Convert a decimal fraction to an int64_t without using
2591 floating point or math libraries. Most decimal fractions
2592 will not fit in an int64_t and this will error out with
2593 under or overflow
2594 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002595static QCBORError Exponentitate2UU(uint64_t nMantissa, int64_t nExponent, uint64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002596{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002597 uint64_t nResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002598
2599 nResult = nMantissa;
2600
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002601 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07002602 * INT64_MAX < 2^31. More than that will cause
2603 * exist with the overflow error
2604 */
2605 while(nExponent > 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002606 if(nResult > UINT64_MAX >> 1) {
2607 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07002608 }
2609 nResult = nResult << 1;
2610 nExponent--;
2611 }
2612
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002613 while(nExponent < 0 ) {
2614 if(nResult == 0) {
2615 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
2616 }
2617 nResult = nResult >> 1;
2618 nExponent--;
2619 }
2620
Laurence Lundbladee6430642020-03-14 21:15:44 -07002621 *pnResult = nResult;
2622
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002623 return QCBOR_SUCCESS;
2624}
2625
2626
2627static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2628{
2629 uint64_t uResult;
2630
2631 // Take the absolute value of the mantissa
2632 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
2633
2634 // Do the exponentiation of the positive mantissa
2635 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
2636 if(uReturn) {
2637 return uReturn;
2638 }
2639
2640 // Error out if too large on the plus side for an int64_t
2641 if(uResult > INT64_MAX) {
2642 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2643 }
2644
2645 // Error out if too large on the negative side for an int64_t
2646 if(uResult < (uint64_t)INT64_MAX+1) {
2647 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
2648 of INT64_MIN. This assumes two's compliment representation where
2649 INT64_MIN is one increment farther from 0 than INT64_MAX.
2650 Trying to write -INT64_MIN doesn't work to get this because the
2651 compiler tries to work with an int64_t which can't represent
2652 -INT64_MIN.
2653 */
2654 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2655 }
2656
2657 // Casts are safe because of checks above
2658 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
2659
2660 return QCBOR_SUCCESS;
2661}
2662
2663
2664static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
2665{
2666 if(nMantissa < 0) {
2667 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
2668 }
2669
2670 // Cast to unsigned is OK because of check for negative
2671 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
2672 // Exponentiation is straight forward
2673 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
2674}
2675
2676
2677// TODO: use this or get rid of it
2678QCBORError ExponentitateUN(uint64_t uMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2679{
2680 uint64_t uResult;
2681
2682 QCBORError uR;
2683
2684 uR = (*pfExp)(uMantissa, nExponent, &uResult);
2685 if(uR) {
2686 return uR;
2687 }
2688
2689 if(uResult > INT64_MAX) {
2690 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2691 }
2692
2693 // Cast is OK because of check above
2694 *pnResult = (int64_t)uResult;
2695
2696 return QCBOR_SUCCESS;
2697}
2698
2699
2700
2701
2702#include <math.h>
2703/*
2704static inline uint8_t Exponentitate10F(uint64_t uMantissa, int64_t nExponent, double *pfResult)
2705{
2706 // TODO: checkout exceptions; what is HUGE_VAL?
2707 *pfResult = pow((double)10, (double)nExponent) * (double)uMantissa;
2708
2709 //if(*pfResult == HUGE_VAL)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002710 return 0;
2711}
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002712*/
2713
2714
2715
2716
2717
Laurence Lundbladee6430642020-03-14 21:15:44 -07002718
2719/*
2720 A) bignum is positive
2721 A1) output is signed INT64_MAX
2722 A2) output is unsigned UINT64_MAX
2723 B) bignum is negative
2724 B1) output is signed INT64_MAX
2725 B2) output is unsigned error
2726 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002727static inline QCBORError ConvertBigNum(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002728{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002729 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002730
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002731 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002732 const uint8_t *pByte = BigNum.ptr;
2733 size_t uLen = BigNum.len;
2734 while(uLen--) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002735 if(uResult > uMax >> 8) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002736 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002737 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002738 uResult = (uResult << 8) + *pByte;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002739 }
2740
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002741 *pResult = uResult;
2742 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002743}
2744
Laurence Lundbladec4537442020-04-14 18:53:22 -07002745
Laurence Lundbladec4537442020-04-14 18:53:22 -07002746
Laurence Lundbladea826c502020-05-10 21:07:00 -07002747static double ConvertBigNumToDouble(const UsefulBufC BigNum)
2748{
2749 double dResult;
2750
2751 dResult = 0.0;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002752 const uint8_t *pByte = BigNum.ptr;
2753 size_t uLen = BigNum.len;
2754 /* This will overflow and become the float value INFINITY if the number
2755 is too large to fit. No error will be logged.
2756 TODO: should an error be logged? */
2757 while(uLen--) {
Laurence Lundbladea826c502020-05-10 21:07:00 -07002758 dResult = (dResult * 256.0) + *pByte;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002759 }
2760
Laurence Lundbladea826c502020-05-10 21:07:00 -07002761 return dResult;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002762}
Laurence Lundbladea826c502020-05-10 21:07:00 -07002763
2764
Laurence Lundbladec4537442020-04-14 18:53:22 -07002765
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002766static inline QCBORError ConvertPositiveBigNumToUnSigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002767{
2768 return ConvertBigNum(BigNum, UINT64_MAX, pResult);
2769}
2770
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002771static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002772{
2773 uint64_t uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002774 QCBORError n = ConvertBigNum(BigNum, INT64_MAX, &uResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002775 if(n) {
2776 return n;
2777 }
2778 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2779 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002780 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002781}
2782
2783
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002784static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002785{
2786 uint64_t uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002787 QCBORError n = ConvertBigNum(BigNum, INT64_MAX-1, &uResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002788 if(n) {
2789 return n;
2790 }
2791 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2792 *pResult = -(int64_t)uResult;
2793 return 0;
2794}
2795
Laurence Lundbladec4537442020-04-14 18:53:22 -07002796// No function to convert a negative bignum to unsigned; it is an error
2797
2798
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002799#if 0
2800static inline int ConvertXYZ(const UsefulBufC Mantissa, int64_t nExponent, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002801{
2802 int64_t nMantissa;
2803
2804 int xx = ConvertPositiveBigNumToSigned(Mantissa, &nMantissa);
2805 if(xx) {
2806 return xx;
2807 }
2808
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002809 return ExponentiateNN(nMantissa, nExponent, pResult, &Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002810}
2811
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002812#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002813
2814
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002815#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07002816
2817/*
2818 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2819 a big float, a decimal fraction or a big num. Conversion will be dones as
2820 expected. Some cases will error out with under or over flow.
2821 */
Laurence Lundbladea826c502020-05-10 21:07:00 -07002822static void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue, QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002823{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002824 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002825 return;
2826 }
2827
Laurence Lundbladee6430642020-03-14 21:15:44 -07002828 QCBORItem Item;
2829 QCBORError nError;
2830
2831 nError = QCBORDecode_GetNext(pMe, &Item);
2832 if(nError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002833 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002834 return;
2835 }
2836
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002837 if(pItem) {
2838 *pItem = Item;
2839 }
2840
Laurence Lundbladee6430642020-03-14 21:15:44 -07002841 switch(Item.uDataType) {
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002842 // TODO: float when ifdefs are set
2843 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002844 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002845 // TODO: what about under/overflow here?
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002846 // Invokes the floating-point HW and/or compiler-added libraries
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002847 feclearexcept(FE_ALL_EXCEPT);
Laurence Lundbladea826c502020-05-10 21:07:00 -07002848 *pValue = llround(Item.val.dfnum);
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002849 if(fetestexcept(FE_INVALID)) {
2850 // TODO: better error code
2851 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2852 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002853 } 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_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002859 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002860 *pValue = Item.val.int64;
2861 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002862 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002863 }
2864 break;
2865
2866 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002867 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002868 if(Item.val.uint64 < INT64_MAX) {
2869 *pValue = Item.val.int64;
2870 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002871 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002872 }
2873 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002874 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002875 }
2876 break;
2877
Laurence Lundbladec4537442020-04-14 18:53:22 -07002878 default:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002879 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002880 }
2881}
2882
Laurence Lundbladea826c502020-05-10 21:07:00 -07002883/* This works for signed, unsigned and float data items */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002884void QCBORDecode_GetInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2885{
2886 QCBORItem Item;
2887 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2888}
2889
2890
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002891// TODO make this inline
2892void QCBORDecode_GetInt64(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2893{
2894 QCBORDecode_GetInt64Convert(pMe, QCBOR_TYPE_INT64, pValue);
2895}
2896
2897
Laurence Lundbladec4537442020-04-14 18:53:22 -07002898
2899/*
2900 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2901 a big float, a decimal fraction or a big num. Conversion will be dones as
2902 expected. Some cases will error out with under or over flow.
2903 */
2904void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2905{
2906 QCBORItem Item;
2907
2908 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2909
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002910 if(pMe->uLastError == QCBOR_SUCCESS) {
2911 // The above conversion succeeded
2912 return;
2913 }
2914
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002915 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002916 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07002917 return;
2918 }
2919
2920 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002921
2922 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002923 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002924 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002925 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002926 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002927 }
2928 break;
2929
2930 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002931 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002932 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002933 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002934 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002935 }
2936 break;
2937
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002938#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2939 case QCBOR_TYPE_DECIMAL_FRACTION:
2940 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002941 pMe->uLastError = (uint8_t)ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002942 Item.val.expAndMantissa.nExponent,
2943 pValue,
2944 &Exponentitate10UU);
2945 } else {
2946 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2947 }
2948 break;
2949
2950 case QCBOR_TYPE_BIGFLOAT:
2951 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002952 pMe->uLastError = (uint8_t)ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002953 Item.val.expAndMantissa.nExponent,
2954 pValue,
2955 &Exponentitate2UU);
2956 } else {
2957 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2958 }
2959 break;
2960
2961
Laurence Lundbladee6430642020-03-14 21:15:44 -07002962 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002963 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002964 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002965 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002966 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002967 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002968 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002969 pValue,
2970 &Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002971 }
2972 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002973 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002974 }
2975 break;
2976
2977 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002978 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002979 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002980 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002981 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002982 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002983 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002984 pValue,
2985 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002986 }
2987 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002988 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002989 }
2990 break;
2991
2992 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002993 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002994 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002995 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002996 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002997 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002998 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002999 pValue,
3000 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003001 }
3002 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003003 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003004 }
3005 break;
3006
3007 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003008 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003009 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003010 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003011 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003012 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003013 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003014 pValue,
3015 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003016 }
3017 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003018 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003019 }
3020 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003021
3022 default:
3023 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
3024#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07003025 }
3026}
3027
Laurence Lundbladec4537442020-04-14 18:53:22 -07003028
3029
3030void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue, QCBORItem *pItem)
3031{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003032 if(pMe->uLastError != QCBOR_SUCCESS) {
3033 return;
3034 }
3035
Laurence Lundbladec4537442020-04-14 18:53:22 -07003036 QCBORItem Item;
3037 QCBORError nError;
3038
3039 nError = QCBORDecode_GetNext(pMe, &Item);
3040 if(nError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003041 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003042 return;
3043 }
3044
Laurence Lundbladea826c502020-05-10 21:07:00 -07003045 if(pItem) {
3046 *pItem = Item;
3047 }
3048
Laurence Lundbladec4537442020-04-14 18:53:22 -07003049 switch(Item.uDataType) {
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003050 // TODO: type flaot
3051 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003052 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003053 feclearexcept(FE_ALL_EXCEPT);
3054 double dRounded = round(Item.val.dfnum);
3055 // TODO: over/underflow
3056 if(fetestexcept(FE_INVALID)) {
3057 // TODO: better error code
3058 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3059 } else if(isnan(dRounded)) {
3060 // TODO: better error code
3061 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3062 } else if(dRounded >= 0) {
3063 *pValue = (uint64_t)dRounded;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003064 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003065 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003066 }
3067 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003068 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003069 }
3070 break;
3071
3072 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003073 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003074 if(Item.val.int64 >= 0) {
3075 *pValue = (uint64_t)Item.val.int64;
3076 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003077 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003078 }
3079 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003080 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003081 }
3082 break;
3083
3084 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003085 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003086 *pValue = Item.val.uint64;
3087 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003088 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003089 }
3090 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003091
3092 default:
3093 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003094 }
3095}
3096
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003097
3098/* This works for signed, unsigned and float */
3099void QCBORDecode_GetUInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003100{
3101 QCBORItem Item;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003102 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
3103}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003104
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003105
3106// TODO make this inline
3107void QCBORDecode_GetUInt64(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
3108{
3109 QCBORDecode_GetUInt64Convert(pMe, QCBOR_TYPE_UINT64, pValue);
3110}
3111
3112
3113
3114
3115void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
3116{
3117 QCBORItem Item;
3118
3119 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
3120
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003121 if(pMe->uLastError == QCBOR_SUCCESS) {
3122 // The above conversion succeeded
3123 return;
3124 }
3125
3126 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3127 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07003128 return;
3129 }
3130
Laurence Lundbladee6430642020-03-14 21:15:44 -07003131 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003132
3133 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003134 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003135 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToUnSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003136 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003137 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003138 }
3139 break;
3140
3141 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003142 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003143 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToUnSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003144 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003145 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003146 }
3147 break;
3148
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003149#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3150
3151 case QCBOR_TYPE_DECIMAL_FRACTION:
3152 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003153 pMe->uLastError = (uint8_t)ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003154 Item.val.expAndMantissa.nExponent,
3155 pValue,
3156 Exponentitate10UU);
3157 } else {
3158 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
3159 }
3160 break;
3161
3162 case QCBOR_TYPE_BIGFLOAT:
3163 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003164 pMe->uLastError = (uint8_t)ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003165 Item.val.expAndMantissa.nExponent,
3166 pValue,
3167 Exponentitate2UU);
3168 } else {
3169 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
3170 }
3171 break;
3172
3173
3174
Laurence Lundbladee6430642020-03-14 21:15:44 -07003175 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003176 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003177 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003178 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003179 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003180 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003181 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003182 pValue,
3183 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003184 }
3185 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003186 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003187 }
3188 break;
3189
3190 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003191 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003192 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003193 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003194 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003195 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003196 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003197 pValue,
3198 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003199 }
3200 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003201 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003202 }
3203 break;
3204
3205 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003206 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003207 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003208 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003209 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003210 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003211 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003212 pValue,
3213 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003214 }
3215 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003216 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003217 }
3218 break;
3219
3220 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003221 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003222 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003223 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003224 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003225 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003226 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003227 pValue,
3228 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003229 }
3230 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003231 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003232 }
3233 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003234#endif
3235 default:
3236 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003237 }
3238}
3239
Laurence Lundbladec4537442020-04-14 18:53:22 -07003240
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003241
Laurence Lundbladec4537442020-04-14 18:53:22 -07003242/*
3243
3244 Convert from bignums,
3245
Laurence Lundbladea826c502020-05-10 21:07:00 -07003246 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
3247
Laurence Lundbladec4537442020-04-14 18:53:22 -07003248 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003249void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003250{
3251 /* the same range of conversions */
3252
Laurence Lundbladec4537442020-04-14 18:53:22 -07003253 QCBORItem Item;
3254 QCBORError nError;
3255
3256 nError = QCBORDecode_GetNext(pMe, &Item);
3257 if(nError) {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003258 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003259 return;
3260 }
3261
Laurence Lundbladec4537442020-04-14 18:53:22 -07003262
3263 switch(Item.uDataType) {
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003264 // TODO: type float
3265 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003266 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003267 *pValue = Item.val.dfnum;
3268 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003269 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003270 }
3271 break;
3272
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003273 case QCBOR_TYPE_INT64:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003274 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003275 // TODO: how does this work?
3276 *pValue = (double)Item.val.int64;
3277 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003278 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003279 }
3280 break;
3281
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003282 case QCBOR_TYPE_UINT64:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003283 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3284 // TODO: check more carefully how this cast works.
Laurence Lundbladec4537442020-04-14 18:53:22 -07003285 *pValue = (double)Item.val.uint64;
3286 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003287 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003288 }
Laurence Lundbladea826c502020-05-10 21:07:00 -07003289
Laurence Lundbladec4537442020-04-14 18:53:22 -07003290
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003291 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003292 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3293 // TODO: rounding and overflow errors
3294 *pValue = (double)Item.val.expAndMantissa.Mantissa.nInt *
3295 pow(10.0, (double)Item.val.expAndMantissa.nExponent);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003296 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003297 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003298 }
3299 break;
3300
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003301 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003302 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
3303 *pValue = (double)Item.val.expAndMantissa.Mantissa.nInt *
3304 exp2((double)Item.val.expAndMantissa.nExponent);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003305 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003306 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003307 }
3308 break;
3309
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003310 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003311 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3312 *pValue = ConvertBigNumToDouble(Item.val.bigNum);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003313 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003314 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003315 }
3316 break;
3317
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003318 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003319 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3320 *pValue = -ConvertBigNumToDouble(Item.val.bigNum);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003321 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003322 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003323 }
3324 break;
3325
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003326 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladea826c502020-05-10 21:07:00 -07003327 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3328 double dMantissa = ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
3329 *pValue = dMantissa * pow(10, (double)Item.val.expAndMantissa.nExponent);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003330 } else {
Laurence Lundbladea826c502020-05-10 21:07:00 -07003331 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003332 }
3333 break;
3334
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003335 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3336 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3337 double dMantissa = -ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
3338 *pValue = dMantissa * pow(10, (double)Item.val.expAndMantissa.nExponent);
3339 } else {
3340 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3341 }
3342 break;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003343
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003344 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3345 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3346 double dMantissa = ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
3347 *pValue = dMantissa * exp2((double)Item.val.expAndMantissa.nExponent);
3348 } else {
3349 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3350 }
3351 break;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003352
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003353 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3354 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3355 double dMantissa = -ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
3356 *pValue = dMantissa * exp2((double)Item.val.expAndMantissa.nExponent);
3357 } else {
3358 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3359 }
3360 break;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003361 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07003362}
3363