blob: 81cc1fdb29596f2a1e03b34bc8a3e5ad9afc0ce7 [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 Lundbladeee851742020-01-08 08:37:05 -0800115inline static int
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700116// TODO: make this bool
117// TODO: add Map as array?
Laurence Lundbladeee851742020-01-08 08:37:05 -0800118IsMapOrArray(uint8_t uDataType)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700119{
120 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
121}
122
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700123inline static bool
124DecodeNesting_IsAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700125{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700126 if(pNesting->pCurrent == &(pNesting->pMapsAndArrays[0])) {
127 return true;
128 } else {
129 return false;
130 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700131}
132
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700133// Determine if at the end of a map or array, taking into
134// account map mode. If this returns true, it is OK
135// to get another item.
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700136inline static bool
137DecodeNesting_AtEnd(const QCBORDecodeNesting *pNesting)
138{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700139 if(DecodeNesting_IsAtTop(pNesting)){
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700140 // Always at end if at the top level of nesting
141 return true;
142 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700143
144 if(pNesting->pCurrent->uMapMode) {
145 if(pNesting->pCurrent->uCount == 0) {
146 // In map mode and consumed all items, so it is the end
147 return true;
148 } else {
149 // In map mode, all items not consumed, so it is NOT the end
150 return false;
151 }
152 } else {
153 // Not in map mode, and not at top level so it NOT the end.
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700154 return false;
155 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700156}
157
158
Laurence Lundbladeee851742020-01-08 08:37:05 -0800159inline static int
160DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700161{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700162 return pNesting->pCurrent->uCount == UINT16_MAX;
163}
164
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700165inline static int
166DecodeNesting_InMapMode(const QCBORDecodeNesting *pNesting)
167{
168 return (bool)pNesting->pCurrent->uMapMode;
169}
170
Laurence Lundbladeee851742020-01-08 08:37:05 -0800171inline static uint8_t
172DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800173{
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800174 // Check in DecodeNesting_Descend and never having
Laurence Lundbladebb87be22020-04-09 19:15:32 -0700175 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800176 return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800177}
178
Laurence Lundbladeee851742020-01-08 08:37:05 -0800179inline static int
180DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700181{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700182 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700183 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700184 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800185
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700186 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
187}
188
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800189// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800190inline static QCBORError
191DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700192{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800193 // breaks must always occur when there is nesting
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700194 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800195 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700196 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800197
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800198 // breaks can only occur when the map/array is indefinite length
199 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
200 return QCBOR_ERR_BAD_BREAK;
201 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800202
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800203 // if all OK, the break reduces the level of nesting
204 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800205
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800206 return QCBOR_SUCCESS;
207}
208
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700209// Called on every single item except breaks including decode of a map/array
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700210/* Decrements the map/array counter if possible. If decrement
211 closed out a map or array, then level up in nesting and decrement
212 again, until, the top is reached or the end of a map mode is reached
213 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800214inline static void
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700215DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800216{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700217 while(!DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700218 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800219
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800220 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700221 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800222 pNesting->pCurrent->uCount--;
223 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700224
225 if(pNesting->pCurrent->uCount != 0) {
226 // Did not close out an array or map, so nothing further
227 break;
228 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700229
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700230 if(pNesting->pCurrent->uMapMode) {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700231 // In map mode the level-up must be done explicitly
232 break;
233 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700234
235 // Closed out an array or map so level up
236 pNesting->pCurrent--;
237
238 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700239 }
240}
241
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700242inline static void
243DecodeNesting_EnterMapMode(QCBORDecodeNesting *pNesting, size_t uOffset)
244{
245 pNesting->pCurrent->uMapMode = 1;
246 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
247 pNesting->pCurrent->uOffset = (uint32_t)uOffset;
248}
249
250inline static void
251DecodeNesting_Exit(QCBORDecodeNesting *pNesting)
252{
253 pNesting->pCurrent->uMapMode = 0;
254 pNesting->pCurrent--;
255
256 DecodeNesting_DecrementCount(pNesting);
257}
258
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800259// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800260inline static QCBORError
261DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700262{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700263 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800264
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800265 if(pItem->val.uCount == 0) {
266 // Nothing to do for empty definite lenth arrays. They are just are
267 // effectively the same as an item that is not a map or array
268 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530269 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800270 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800271
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800272 // Error out if arrays is too long to handle
273 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700274 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
275 goto Done;
276 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800277
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800278 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700279 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
280 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
281 goto Done;
282 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800283
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800284 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700285 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800286
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800287 // Record a few details for this nesting level
288 pNesting->pCurrent->uMajorType = pItem->uDataType;
289 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700290 pNesting->pCurrent->uSaveCount = pItem->val.uCount;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700291 pNesting->pCurrent->uMapMode = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800292
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700293Done:
294 return nReturn;;
295}
296
Laurence Lundbladeee851742020-01-08 08:37:05 -0800297inline static void
298DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700299{
300 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
301}
302
303
304
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700305/*
306 This list of built-in tags. Only add tags here that are
307 clearly established and useful. Once a tag is added here
308 it can't be taken out as that would break backwards compatibility.
309 There are only 48 slots available forever.
310 */
311static const uint16_t spBuiltInTagMap[] = {
Laurence Lundblade59289e52019-12-30 13:44:37 -0800312 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
313 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
314 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
315 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
316 CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
317 CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700318 CBOR_TAG_COSE_ENCRYPTO,
319 CBOR_TAG_COSE_MAC0,
320 CBOR_TAG_COSE_SIGN1,
321 CBOR_TAG_ENC_AS_B64URL,
322 CBOR_TAG_ENC_AS_B64,
323 CBOR_TAG_ENC_AS_B16,
324 CBOR_TAG_CBOR,
325 CBOR_TAG_URI,
326 CBOR_TAG_B64URL,
327 CBOR_TAG_B64,
328 CBOR_TAG_REGEX,
329 CBOR_TAG_MIME,
330 CBOR_TAG_BIN_UUID,
331 CBOR_TAG_CWT,
332 CBOR_TAG_ENCRYPT,
333 CBOR_TAG_MAC,
334 CBOR_TAG_SIGN,
335 CBOR_TAG_GEO_COORD,
336 CBOR_TAG_CBOR_MAGIC
337};
338
339// This is used in a bit of cleverness in GetNext_TaggedItem() to
340// keep code size down and switch for the internal processing of
Laurence Lundblade59289e52019-12-30 13:44:37 -0800341// these types. This will break if the first six items in
342// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
343// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
344#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
345#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
346#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
347#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
348#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
349#define QCBOR_TAGFLAG_BIGFLOAT (0x01LL << CBOR_TAG_BIGFLOAT)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700350
Laurence Lundblade59289e52019-12-30 13:44:37 -0800351#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING |\
352 QCBOR_TAGFLAG_DATE_EPOCH |\
353 QCBOR_TAGFLAG_POS_BIGNUM |\
354 QCBOR_TAGFLAG_NEG_BIGNUM |\
355 QCBOR_TAGFLAG_DECIMAL_FRACTION |\
356 QCBOR_TAGFLAG_BIGFLOAT)
357
358#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
359 QCBOR_TAGFLAG_DATE_EPOCH |\
360 QCBOR_TAGFLAG_POS_BIGNUM |\
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700361 QCBOR_TAGFLAG_NEG_BIGNUM)
362
363#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
364#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
365#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
366
367static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
368{
369 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800370 /*
371 This is a cross-check to make sure the above array doesn't
372 accidentally get made too big. In normal conditions the above
373 test should optimize out as all the values are known at compile
374 time.
375 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700376 return -1;
377 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800378
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700379 if(uTag > UINT16_MAX) {
380 // This tag map works only on 16-bit tags
381 return -1;
382 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800383
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700384 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
385 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
386 return nTagBitIndex;
387 }
388 }
389 return -1; // Indicates no match
390}
391
392static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
393{
394 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
395 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
396 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
397 }
398 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800399
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700400 return -1; // Indicates no match
401}
402
403/*
404 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800405
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700406 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800407 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700408 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800409static QCBORError
410TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
411 uint64_t uTag,
412 uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700413{
414 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
415 if(nTagBitIndex >= 0) {
416 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
417 *puTagBitIndex = (uint8_t)nTagBitIndex;
418 return QCBOR_SUCCESS;
419 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800420
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700421 if(pCallerConfiguredTagMap) {
422 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
423 return QCBOR_ERR_TOO_MANY_TAGS;
424 }
425 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
426 if(nTagBitIndex >= 0) {
427 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
428
429 *puTagBitIndex = (uint8_t)nTagBitIndex;
430 return QCBOR_SUCCESS;
431 }
432 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800433
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700434 return QCBOR_ERR_BAD_OPT_TAG;
435}
436
437
438
Laurence Lundbladeee851742020-01-08 08:37:05 -0800439/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800440 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
441
442 The following four functions are pretty wrappers for invocation of
443 the string allocator supplied by the caller.
444
Laurence Lundbladeee851742020-01-08 08:37:05 -0800445 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800446
Laurence Lundbladeee851742020-01-08 08:37:05 -0800447static inline void
448StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800449{
450 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
451}
452
Laurence Lundbladeee851742020-01-08 08:37:05 -0800453// StringAllocator_Reallocate called with pMem NULL is
454// equal to StringAllocator_Allocate()
455static inline UsefulBuf
456StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
457 void *pMem,
458 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800459{
460 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
461}
462
Laurence Lundbladeee851742020-01-08 08:37:05 -0800463static inline UsefulBuf
464StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800465{
466 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
467}
468
Laurence Lundbladeee851742020-01-08 08:37:05 -0800469static inline void
470StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800471{
472 if(pMe->pfAllocator) {
473 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
474 }
475}
476
477
478
Laurence Lundbladeee851742020-01-08 08:37:05 -0800479/*===========================================================================
480 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700481
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800482 See qcbor/qcbor_decode.h for definition of the object
483 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800484 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700485/*
486 Public function, see header file
487 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800488void QCBORDecode_Init(QCBORDecodeContext *me,
489 UsefulBufC EncodedCBOR,
490 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700491{
492 memset(me, 0, sizeof(QCBORDecodeContext));
493 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800494 // Don't bother with error check on decode mode. If a bad value is
495 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700496 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700497 DecodeNesting_Init(&(me->nesting));
498}
499
500
501/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700502 Public function, see header file
503 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800504void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
505 QCBORStringAllocate pfAllocateFunction,
506 void *pAllocateContext,
507 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700508{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800509 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
510 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
511 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700512}
513
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800514
515/*
516 Public function, see header file
517 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800518void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
519 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700520{
521 me->pCallerConfiguredTagList = pTagList;
522}
523
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700524
525/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800526 This decodes the fundamental part of a CBOR data item, the type and
527 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800528
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700529 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800530
Laurence Lundbladeee851742020-01-08 08:37:05 -0800531 This does the network->host byte order conversion. The conversion
532 here also results in the conversion for floats in addition to that
533 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800534
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700535 This returns:
536 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800537
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800538 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800539 tags and floats and length for strings and arrays
540
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800541 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800542 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800543
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800544 The int type is preferred to uint8_t for some variables as this
545 avoids integer promotions, can reduce code size and makes
546 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700547 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800548inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
549 int *pnMajorType,
550 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800551 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700552{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700553 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800554
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700555 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800556 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800557
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700558 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800559 const int nTmpMajorType = nInitialByte >> 5;
560 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800561
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800562 // Where the number or argument accumulates
563 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800564
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800565 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800566 // Need to get 1,2,4 or 8 additional argument bytes Map
567 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800568 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800569
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800570 // Loop getting all the bytes in the argument
571 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800572 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800573 // This shift and add gives the endian conversion
574 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
575 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800576 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800577 // The reserved and thus-far unused additional info values
578 nReturn = QCBOR_ERR_UNSUPPORTED;
579 goto Done;
580 } else {
581 // Less than 24, additional info is argument or 31, an indefinite length
582 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800583 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700584 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800585
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700586 if(UsefulInputBuf_GetError(pUInBuf)) {
587 nReturn = QCBOR_ERR_HIT_END;
588 goto Done;
589 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800590
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700591 // All successful if we got here.
592 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800593 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800594 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800595 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800596
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700597Done:
598 return nReturn;
599}
600
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800601
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700602/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800603 CBOR doesn't explicitly specify two's compliment for integers but all
604 CPUs use it these days and the test vectors in the RFC are so. All
605 integers in the CBOR structure are positive and the major type
606 indicates positive or negative. CBOR can express positive integers
607 up to 2^x - 1 where x is the number of bits and negative integers
608 down to 2^x. Note that negative numbers can be one more away from
609 zero than positive. Stdint, as far as I can tell, uses two's
610 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800611
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700612 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800613 used carefully here, and in particular why it isn't used in the interface.
614 Also see
615 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
616
617 Int is used for values that need less than 16-bits and would be subject
618 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700619 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800620inline static QCBORError
621DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700622{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700623 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800624
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700625 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
626 if (uNumber <= INT64_MAX) {
627 pDecodedItem->val.int64 = (int64_t)uNumber;
628 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800629
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700630 } else {
631 pDecodedItem->val.uint64 = uNumber;
632 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800633
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700634 }
635 } else {
636 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800637 // CBOR's representation of negative numbers lines up with the
638 // two-compliment representation. A negative integer has one
639 // more in range than a positive integer. INT64_MIN is
640 // equal to (-INT64_MAX) - 1.
641 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700642 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800643
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700644 } else {
645 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000646 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700647 nReturn = QCBOR_ERR_INT_OVERFLOW;
648 }
649 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800650
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651 return nReturn;
652}
653
654// Make sure #define value line up as DecodeSimple counts on this.
655#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
656#error QCBOR_TYPE_FALSE macro value wrong
657#endif
658
659#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
660#error QCBOR_TYPE_TRUE macro value wrong
661#endif
662
663#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
664#error QCBOR_TYPE_NULL macro value wrong
665#endif
666
667#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
668#error QCBOR_TYPE_UNDEF macro value wrong
669#endif
670
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700671#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
672#error QCBOR_TYPE_BREAK macro value wrong
673#endif
674
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700675#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
676#error QCBOR_TYPE_DOUBLE macro value wrong
677#endif
678
679#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
680#error QCBOR_TYPE_FLOAT macro value wrong
681#endif
682
683/*
684 Decode true, false, floats, break...
685 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800686inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800687DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700688{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700689 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800690
Laurence Lundbladeee851742020-01-08 08:37:05 -0800691 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800692 // above make sure uAdditionalInfo values line up with uDataType values.
693 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
694 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800695
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800696 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800697 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
698 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800699
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700700 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700701 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
702 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700703 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700704 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700705 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
706 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700707 break;
708 case DOUBLE_PREC_FLOAT:
709 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700710 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700711 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800712
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700713 case CBOR_SIMPLEV_FALSE: // 20
714 case CBOR_SIMPLEV_TRUE: // 21
715 case CBOR_SIMPLEV_NULL: // 22
716 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700717 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700718 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800719
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700720 case CBOR_SIMPLEV_ONEBYTE: // 24
721 if(uNumber <= CBOR_SIMPLE_BREAK) {
722 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700723 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724 goto Done;
725 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800726 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700727 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800728
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700729 default: // 0-19
730 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800731 /*
732 DecodeTypeAndNumber will make uNumber equal to
733 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
734 safe because the 2, 4 and 8 byte lengths of uNumber are in
735 the double/float cases above
736 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700737 pDecodedItem->val.uSimple = (uint8_t)uNumber;
738 break;
739 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800740
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700741Done:
742 return nReturn;
743}
744
745
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530747 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700748 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800749inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
750 int nMajorType,
751 uint64_t uStrLen,
752 UsefulInputBuf *pUInBuf,
753 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700754{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700755 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800756
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800757 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
758 // This check makes the casts to size_t below safe.
759
760 // 4 bytes less than the largest sizeof() so this can be tested by
761 // putting a SIZE_MAX length in the CBOR test input (no one will
762 // care the limit on strings is 4 bytes shorter).
763 if(uStrLen > SIZE_MAX-4) {
764 nReturn = QCBOR_ERR_STRING_TOO_LONG;
765 goto Done;
766 }
767
768 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530769 if(UsefulBuf_IsNULLC(Bytes)) {
770 // Failed to get the bytes for this string item
771 nReturn = QCBOR_ERR_HIT_END;
772 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700773 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530774
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800775 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530776 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800777 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530778 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700779 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530780 goto Done;
781 }
782 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800783 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530784 } else {
785 // Normal case with no string allocator
786 pDecodedItem->val.string = Bytes;
787 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800788 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800789 // Cast because ternary operator causes promotion to integer
790 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
791 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800792
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530793Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700794 return nReturn;
795}
796
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700797
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800798
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700799
800
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700801
802
Laurence Lundbladeee851742020-01-08 08:37:05 -0800803// Make sure the constants align as this is assumed by
804// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700805#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
806#error QCBOR_TYPE_ARRAY value not lined up with major type
807#endif
808#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
809#error QCBOR_TYPE_MAP value not lined up with major type
810#endif
811
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700812/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800813 This gets a single data item and decodes it including preceding
814 optional tagging. This does not deal with arrays and maps and nesting
815 except to decode the data item introducing them. Arrays and maps are
816 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800817
Laurence Lundbladeee851742020-01-08 08:37:05 -0800818 Errors detected here include: an array that is too long to decode,
819 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700820 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800821static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
822 QCBORItem *pDecodedItem,
823 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700824{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700825 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800826
Laurence Lundbladeee851742020-01-08 08:37:05 -0800827 /*
828 Get the major type and the number. Number could be length of more
829 bytes or the value depending on the major type nAdditionalInfo is
830 an encoding of the length of the uNumber and is needed to decode
831 floats and doubles
832 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800833 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700834 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800835 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800836
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700837 memset(pDecodedItem, 0, sizeof(QCBORItem));
838
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800839 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800840
Laurence Lundbladeee851742020-01-08 08:37:05 -0800841 // Error out here if we got into trouble on the type and number. The
842 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700843 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700844 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700845 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800846
Laurence Lundbladeee851742020-01-08 08:37:05 -0800847 // At this point the major type and the value are valid. We've got
848 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800849 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700850 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
851 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800852 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700853 nReturn = QCBOR_ERR_BAD_INT;
854 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800855 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700856 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700857 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800858
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700859 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
860 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800861 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
862 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
863 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
864 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530865 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700866 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800867 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700868 }
869 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800870
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700871 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
872 case CBOR_MAJOR_TYPE_MAP: // Major type 5
873 // Record the number of items in the array or map
874 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
875 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
876 goto Done;
877 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800878 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530879 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700880 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800881 // type conversion OK because of check above
882 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700883 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800884 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800885 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
886 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700887 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800888
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700889 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800890 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700891 nReturn = QCBOR_ERR_BAD_INT;
892 } else {
893 pDecodedItem->val.uTagV = uNumber;
894 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
895 }
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 case CBOR_MAJOR_TYPE_SIMPLE:
899 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800900 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700901 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800902
Laurence Lundbladeee851742020-01-08 08:37:05 -0800903 default:
904 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700905 nReturn = QCBOR_ERR_UNSUPPORTED;
906 break;
907 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800908
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700909Done:
910 return nReturn;
911}
912
913
914
915/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800916 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800917 individual chunk items together into one QCBORItem using the string
918 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800919
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530920 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700921 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800922static inline QCBORError
923GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700924{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700925 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700926
927 // Get pointer to string allocator. First use is to pass it to
928 // GetNext_Item() when option is set to allocate for *every* string.
929 // Second use here is to allocate space to coallese indefinite
930 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800931 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
932 &(me->StringAllocator) :
933 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800934
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700935 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800936 nReturn = GetNext_Item(&(me->InBuf),
937 pDecodedItem,
938 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700939 if(nReturn) {
940 goto Done;
941 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800942
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700943 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530944 // code in this function from here down can be eliminated. Run tests, except
945 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800946
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800947 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700948 const uint8_t uStringType = pDecodedItem->uDataType;
949 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700950 goto Done; // no need to do any work here on non-string types
951 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800952
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800953 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530954 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800955 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700956 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800957
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530958 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800959 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700960 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
961 goto Done;
962 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800963
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700964 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700965 UsefulBufC FullString = NULLUsefulBufC;
966
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700967 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700968 // Get item for next chunk
969 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700970 // NULL string allocator passed here. Do not need to allocate
971 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800972 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700973 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700974 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700975 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800976
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530977 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700978 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800979 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700980 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530981 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700982 break;
983 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800984
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700985 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530986 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700987 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800988 if(StringChunkItem.uDataType != uStringType ||
989 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700990 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700991 break;
992 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800993
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530994 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800995 // The first time throurgh FullString.ptr is NULL and this is
996 // equivalent to StringAllocator_Allocate()
997 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
998 UNCONST_POINTER(FullString.ptr),
999 FullString.len + StringChunkItem.val.string.len);
1000
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001001 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301002 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001003 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001004 break;
1005 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001006
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001007 // Copy new string chunk at the end of string so far.
1008 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001010
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001011 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1012 // Getting the item failed, clean up the allocated memory
1013 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001014 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001015
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001016Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001017 return nReturn;
1018}
1019
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001020
1021/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001022 Gets all optional tag data items preceding a data item that is not an
1023 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001024 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001025static QCBORError
1026GetNext_TaggedItem(QCBORDecodeContext *me,
1027 QCBORItem *pDecodedItem,
1028 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001029{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001030 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +07001031 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001032 uint64_t uTagBits = 0;
1033 if(pTags) {
1034 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001035 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001036
Laurence Lundblade59289e52019-12-30 13:44:37 -08001037 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001038 for(;;) {
1039 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001040 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001041 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001042 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001043
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001044 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1045 // Successful exit from loop; maybe got some tags, maybe not
1046 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001047 break;
1048 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001049
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001050 uint8_t uTagBitIndex;
1051 // Tag was mapped, tag was not mapped, error with tag list
1052 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001053
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001054 case QCBOR_SUCCESS:
1055 // Successfully mapped the tag
1056 uTagBits |= 0x01ULL << uTagBitIndex;
1057 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001058
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001059 case QCBOR_ERR_BAD_OPT_TAG:
1060 // Tag is not recognized. Do nothing
1061 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001062
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001063 default:
1064 // Error Condition
1065 goto Done;
1066 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001067
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001068 if(pTags) {
1069 // Caller wants all tags recorded in the provided buffer
1070 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1071 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
1072 goto Done;
1073 }
1074 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
1075 pTags->uNumUsed++;
1076 }
1077 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001078
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001079Done:
1080 return nReturn;
1081}
1082
1083
1084/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001085 This layer takes care of map entries. It combines the label and data
1086 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001087 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001088static inline QCBORError
1089GetNext_MapEntry(QCBORDecodeContext *me,
1090 QCBORItem *pDecodedItem,
1091 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001092{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001093 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +07001094 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001095 if(nReturn)
1096 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001097
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001098 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001099 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001100 goto Done;
1101 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001102
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001103 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1104 // In a map and caller wants maps decoded, not treated as arrays
1105
1106 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1107 // If in a map and the right decoding mode, get the label
1108
Laurence Lundbladeee851742020-01-08 08:37:05 -08001109 // Save label in pDecodedItem and get the next which will
1110 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001111 QCBORItem LabelItem = *pDecodedItem;
1112 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1113 if(nReturn)
1114 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001115
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301116 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001117
1118 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1119 // strings are always good labels
1120 pDecodedItem->label.string = LabelItem.val.string;
1121 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1122 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001123 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001124 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1125 goto Done;
1126 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1127 pDecodedItem->label.int64 = LabelItem.val.int64;
1128 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1129 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1130 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1131 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1132 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1133 pDecodedItem->label.string = LabelItem.val.string;
1134 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1135 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1136 } else {
1137 // label is not an int or a string. It is an arrray
1138 // or a float or such and this implementation doesn't handle that.
1139 // Also, tags on labels are ignored.
1140 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1141 goto Done;
1142 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001143 }
1144 } else {
1145 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001146 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1147 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1148 goto Done;
1149 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001150 // Decoding a map as an array
1151 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001152 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1153 // Cast is needed because of integer promotion
1154 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001155 }
1156 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001157
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001158Done:
1159 return nReturn;
1160}
1161
1162
1163/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001164 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001165 TODO: correct this comment
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001166 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001167QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
1168 QCBORItem *pDecodedItem,
1169 QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001170{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001171 // Stack ptr/int: 2, QCBORItem : 64
1172
Laurence Lundblade30816f22018-11-10 13:40:22 +07001173 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001174
Laurence Lundblade1341c592020-04-11 14:19:05 -07001175 // Check if there are an TODO: incomplete comment
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 Lundblade3f9ef042020-04-14 13:15:51 -07001180
1181 // This is to handle map and array mode
1182 if(UsefulInputBuf_Tell(&(me->InBuf)) != 0 && DecodeNesting_AtEnd(&(me->nesting))) {
1183 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1184 goto Done;
1185 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001186
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001187 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001188 if(nReturn) {
1189 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001190 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301191
1192 // Break ending arrays/maps are always processed at the end of this function.
1193 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301194 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301195 nReturn = QCBOR_ERR_BAD_BREAK;
1196 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301197 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001198
Laurence Lundblade6de37062018-10-15 12:22:42 +05301199 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301200 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301201 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001202
Laurence Lundblade6de37062018-10-15 12:22:42 +05301203 // Process the item just received for descent or decrement, and
1204 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001205 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001206 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001207 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001208 // Maps and arrays do count in as items in the map/array that encloses
1209 // them so a decrement needs to be done for them too, but that is done
1210 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001211 // are opened with the exception of an empty map or array.
1212 if(pDecodedItem->val.uCount == 0) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001213 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001214 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001215 } else {
1216 // Decrement the count of items in the enclosing map/array
1217 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301218 // triggers a decrement in the map/array above that and
1219 // an ascend in nesting level.
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001220 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001221 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301222 if(nReturn) {
1223 goto Done;
1224 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001225
Laurence Lundblade6de37062018-10-15 12:22:42 +05301226 // For indefinite length maps/arrays, looking at any and
1227 // all breaks that might terminate them. The equivalent
1228 // for definite length maps/arrays happens in
1229 // DecodeNesting_DecrementCount().
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001230 if(!DecodeNesting_IsAtTop(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301231 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1232 // Peek forward one item to see if it is a break.
1233 QCBORItem Peek;
1234 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1235 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1236 if(nReturn) {
1237 goto Done;
1238 }
1239 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1240 // It is not a break, rewind so it can be processed normally.
1241 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1242 break;
1243 }
1244 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301245 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301246 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1247 if(nReturn) {
1248 // break occured outside of an indefinite length array/map
1249 goto Done;
1250 }
1251 }
1252 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001253
Laurence Lundblade6de37062018-10-15 12:22:42 +05301254 // Tell the caller what level is next. This tells them what maps/arrays
1255 // were closed out and makes it possible for them to reconstruct
1256 // the tree with just the information returned by GetNext
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001257 if(me->nesting.pCurrent->uMapMode && me->nesting.pCurrent->uCount == 0) {
1258 // At end of a map / array in map mode, so next nest is 0 to
1259 // indicate this end.
1260 pDecodedItem->uNextNestLevel = 0;
1261 } else {
1262 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
1263 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001264
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001265Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001266 if(nReturn != QCBOR_SUCCESS) {
1267 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1268 memset(pDecodedItem, 0, sizeof(QCBORItem));
1269 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001270 return nReturn;
1271}
1272
1273
Laurence Lundblade59289e52019-12-30 13:44:37 -08001274/*
1275 Mostly just assign the right data type for the date string.
1276 */
1277inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1278{
1279 // Stack Use: UsefulBuf 1 16
1280 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1281 return QCBOR_ERR_BAD_OPT_TAG;
1282 }
1283
1284 const UsefulBufC Temp = pDecodedItem->val.string;
1285 pDecodedItem->val.dateString = Temp;
1286 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1287 return QCBOR_SUCCESS;
1288}
1289
1290
1291/*
1292 Mostly just assign the right data type for the bignum.
1293 */
1294inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1295{
1296 // Stack Use: UsefulBuf 1 -- 16
1297 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1298 return QCBOR_ERR_BAD_OPT_TAG;
1299 }
1300 const UsefulBufC Temp = pDecodedItem->val.string;
1301 pDecodedItem->val.bigNum = Temp;
Laurence Lundbladeee851742020-01-08 08:37:05 -08001302 const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001303 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1304 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001305 return QCBOR_SUCCESS;
1306}
1307
1308
1309/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001310 The epoch formatted date. Turns lots of different forms of encoding
1311 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001312 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001313static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001314{
1315 // Stack usage: 1
1316 QCBORError nReturn = QCBOR_SUCCESS;
1317
1318 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1319
1320 switch (pDecodedItem->uDataType) {
1321
1322 case QCBOR_TYPE_INT64:
1323 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1324 break;
1325
1326 case QCBOR_TYPE_UINT64:
1327 if(pDecodedItem->val.uint64 > INT64_MAX) {
1328 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1329 goto Done;
1330 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001331 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001332 break;
1333
1334 case QCBOR_TYPE_DOUBLE:
1335 {
1336 // This comparison needs to be done as a float before
1337 // conversion to an int64_t to be able to detect doubles
1338 // that are too large to fit into an int64_t. A double
1339 // has 52 bits of preceision. An int64_t has 63. Casting
1340 // INT64_MAX to a double actually causes a round up which
1341 // is bad and wrong for the comparison because it will
1342 // allow conversion of doubles that can't fit into a
1343 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1344 // the cutoff point as if that rounds up in conversion to
1345 // double it will still be less than INT64_MAX. 0x7ff is
1346 // picked because it has 11 bits set.
1347 //
1348 // INT64_MAX seconds is on the order of 10 billion years,
1349 // and the earth is less than 5 billion years old, so for
1350 // most uses this conversion error won't occur even though
1351 // doubles can go much larger.
1352 //
1353 // Without the 0x7ff there is a ~30 minute range of time
1354 // values 10 billion years in the past and in the future
1355 // where this this code would go wrong.
1356 const double d = pDecodedItem->val.dfnum;
1357 if(d > (double)(INT64_MAX - 0x7ff)) {
1358 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1359 goto Done;
1360 }
1361 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1362 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1363 }
1364 break;
1365
1366 default:
1367 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1368 goto Done;
1369 }
1370 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1371
1372Done:
1373 return nReturn;
1374}
1375
1376
1377#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1378/*
1379 Decode decimal fractions and big floats.
1380
1381 When called pDecodedItem must be the array that is tagged as a big
1382 float or decimal fraction, the array that has the two members, the
1383 exponent and mantissa.
1384
1385 This will fetch and decode the exponent and mantissa and put the
1386 result back into pDecodedItem.
1387 */
1388inline static QCBORError
1389QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1390{
1391 QCBORError nReturn;
1392
1393 // --- Make sure it is an array; track nesting level of members ---
1394 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1395 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1396 goto Done;
1397 }
1398
1399 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001400 // definite length arrays, but not for indefnite. Instead remember
1401 // the nesting level the two integers must be at, which is one
1402 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001403 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1404
1405 // --- Is it a decimal fraction or a bigfloat? ---
1406 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1407 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1408
1409 // --- Get the exponent ---
1410 QCBORItem exponentItem;
1411 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
1412 if(nReturn != QCBOR_SUCCESS) {
1413 goto Done;
1414 }
1415 if(exponentItem.uNestingLevel != nNestLevel) {
1416 // Array is empty or a map/array encountered when expecting an int
1417 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1418 goto Done;
1419 }
1420 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1421 // Data arriving as an unsigned int < INT64_MAX has been converted
1422 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1423 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1424 // will be too large for this to handle and thus an error that will
1425 // get handled in the next else.
1426 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1427 } else {
1428 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1429 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1430 goto Done;
1431 }
1432
1433 // --- Get the mantissa ---
1434 QCBORItem mantissaItem;
1435 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1436 if(nReturn != QCBOR_SUCCESS) {
1437 goto Done;
1438 }
1439 if(mantissaItem.uNestingLevel != nNestLevel) {
1440 // Mantissa missing or map/array encountered when expecting number
1441 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1442 goto Done;
1443 }
1444 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1445 // Data arriving as an unsigned int < INT64_MAX has been converted
1446 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1447 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1448 // will be too large for this to handle and thus an error that
1449 // will get handled in an else below.
1450 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1451 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1452 // Got a good big num mantissa
1453 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1454 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001455 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1456 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1457 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001458 } else {
1459 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1460 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1461 goto Done;
1462 }
1463
1464 // --- Check that array only has the two numbers ---
1465 if(mantissaItem.uNextNestLevel == nNestLevel) {
1466 // Extra items in the decimal fraction / big num
1467 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1468 goto Done;
1469 }
1470
1471Done:
1472
1473 return nReturn;
1474}
1475#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1476
1477
1478/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001479 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001480 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001481QCBORError
1482QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1483 QCBORItem *pDecodedItem,
1484 QCBORTagListOut *pTags)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001485{
1486 QCBORError nReturn;
1487
1488 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
1489 if(nReturn != QCBOR_SUCCESS) {
1490 goto Done;
1491 }
1492
1493#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1494#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
1495#else
1496#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
1497#endif
1498
1499 // Only pay attention to tags this code knows how to decode.
1500 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
1501 case 0:
1502 // No tags at all or none we know about. Nothing to do.
1503 // This is the pass-through path of this function
1504 // that will mostly be taken when decoding any item.
1505 break;
1506
1507 case QCBOR_TAGFLAG_DATE_STRING:
1508 nReturn = DecodeDateString(pDecodedItem);
1509 break;
1510
1511 case QCBOR_TAGFLAG_DATE_EPOCH:
1512 nReturn = DecodeDateEpoch(pDecodedItem);
1513 break;
1514
1515 case QCBOR_TAGFLAG_POS_BIGNUM:
1516 case QCBOR_TAGFLAG_NEG_BIGNUM:
1517 nReturn = DecodeBigNum(pDecodedItem);
1518 break;
1519
1520#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1521 case QCBOR_TAGFLAG_DECIMAL_FRACTION:
1522 case QCBOR_TAGFLAG_BIGFLOAT:
1523 // For aggregate tagged types, what goes into pTags is only collected
1524 // from the surrounding data item, not the contents, so pTags is not
1525 // passed on here.
1526
1527 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1528 break;
1529#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1530
1531 default:
1532 // Encountering some mixed-up CBOR like something that
1533 // is tagged as both a string and integer date.
1534 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1535 }
1536
1537Done:
1538 if(nReturn != QCBOR_SUCCESS) {
1539 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1540 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1541 }
1542 return nReturn;
1543}
1544
1545
1546/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001547 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001548 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001549QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001550{
1551 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1552}
1553
1554
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001555/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301556 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301557 next one down. If a layer has no work to do for a particular item
1558 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001559
Laurence Lundblade59289e52019-12-30 13:44:37 -08001560 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1561 tagged data items, turning them into the local C representation.
1562 For the most simple it is just associating a QCBOR_TYPE with the data. For
1563 the complex ones that an aggregate of data items, there is some further
1564 decoding and a little bit of recursion.
1565
1566 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301567 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301568 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001569 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001570
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301571 - GetNext_MapEntry -- This handles the combining of two
1572 items, the label and the data, that make up a map entry.
1573 It only does work on maps. It combines the label and data
1574 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001575
Laurence Lundblade59289e52019-12-30 13:44:37 -08001576 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1577 tags into bit flags associated with the data item. No actual decoding
1578 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001579
Laurence Lundblade59289e52019-12-30 13:44:37 -08001580 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301581 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301582 string allocater to create contiguous space for the item. It
1583 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001584
Laurence Lundblade59289e52019-12-30 13:44:37 -08001585 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1586 atomic data item has a "major type", an integer "argument" and optionally
1587 some content. For text and byte strings, the content is the bytes
1588 that make up the string. These are the smallest data items that are
1589 considered to be well-formed. The content may also be other data items in
1590 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001591
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001592 Roughly this takes 300 bytes of stack for vars. Need to
1593 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001594
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301595 */
1596
1597
1598/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001599 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001600 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001601int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1602 const QCBORItem *pItem,
1603 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001604{
1605 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001606
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001607 uint8_t uTagBitIndex;
1608 // Do not care about errors in pCallerConfiguredTagMap here. They are
1609 // caught during GetNext() before this is called.
1610 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1611 return 0;
1612 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001613
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001614 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1615 return (uTagBit & pItem->uTagBits) != 0;
1616}
1617
1618
1619/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001620 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001621 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001622QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001623{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001624 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001625
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001626 // Error out if all the maps/arrays are not closed out
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001627 if(!DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001628 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1629 goto Done;
1630 }
1631
1632 // Error out if not all the bytes are consumed
1633 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1634 nReturn = QCBOR_ERR_EXTRA_BYTES;
1635 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001636
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001637Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301638 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001639 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001640 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001641
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001642 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001643}
1644
1645
1646
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001647/*
1648
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001649Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001650
Laurence Lundbladeee851742020-01-08 08:37:05 -08001651 - Hit end of input before it was expected while decoding type and
1652 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001653
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001654 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001655
Laurence Lundbladeee851742020-01-08 08:37:05 -08001656 - Hit end of input while decoding a text or byte string
1657 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001658
Laurence Lundbladeee851742020-01-08 08:37:05 -08001659 - Encountered conflicting tags -- e.g., an item is tagged both a date
1660 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001661
Laurence Lundbladeee851742020-01-08 08:37:05 -08001662 - Encontered an array or mapp that has too many items
1663 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001664
Laurence Lundbladeee851742020-01-08 08:37:05 -08001665 - Encountered array/map nesting that is too deep
1666 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001667
Laurence Lundbladeee851742020-01-08 08:37:05 -08001668 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1669 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001670
Laurence Lundbladeee851742020-01-08 08:37:05 -08001671 - The type of a map label is not a string or int
1672 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001673
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001674 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001675
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001676 */
1677
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001678
1679
Laurence Lundbladef6531662018-12-04 10:42:22 +09001680
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001681/* ===========================================================================
1682 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001683
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001684 This implements a simple sting allocator for indefinite length
1685 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1686 implements the function type QCBORStringAllocate and allows easy
1687 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001688
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001689 This particular allocator is built-in for convenience. The caller
1690 can implement their own. All of this following code will get
1691 dead-stripped if QCBORDecode_SetMemPool() is not called.
1692
1693 This is a very primitive memory allocator. It does not track
1694 individual allocations, only a high-water mark. A free or
1695 reallocation must be of the last chunk allocated.
1696
1697 The size of the pool and offset to free memory are packed into the
1698 first 8 bytes of the memory pool so we don't have to keep them in
1699 the decode context. Since the address of the pool may not be
1700 aligned, they have to be packed and unpacked as if they were
1701 serialized data of the wire or such.
1702
1703 The sizes packed in are uint32_t to be the same on all CPU types
1704 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001705 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001706
1707
Laurence Lundbladeee851742020-01-08 08:37:05 -08001708static inline int
1709MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001710{
1711 // Use of UsefulInputBuf is overkill, but it is convenient.
1712 UsefulInputBuf UIB;
1713
Laurence Lundbladeee851742020-01-08 08:37:05 -08001714 // Just assume the size here. It was checked during SetUp so
1715 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001716 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1717 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1718 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1719 return UsefulInputBuf_GetError(&UIB);
1720}
1721
1722
Laurence Lundbladeee851742020-01-08 08:37:05 -08001723static inline int
1724MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001725{
1726 // Use of UsefulOutBuf is overkill, but convenient. The
1727 // length check performed here is useful.
1728 UsefulOutBuf UOB;
1729
1730 UsefulOutBuf_Init(&UOB, Pool);
1731 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1732 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1733 return UsefulOutBuf_GetError(&UOB);
1734}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001735
1736
1737/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001738 Internal function for an allocation, reallocation free and destuct.
1739
1740 Having only one function rather than one each per mode saves space in
1741 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001742
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001743 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1744 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001745static UsefulBuf
1746MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001747{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001748 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001749
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001750 uint32_t uPoolSize;
1751 uint32_t uFreeOffset;
1752
1753 if(uNewSize > UINT32_MAX) {
1754 // This allocator is only good up to 4GB. This check should
1755 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1756 goto Done;
1757 }
1758 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1759
1760 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1761 goto Done;
1762 }
1763
1764 if(uNewSize) {
1765 if(pMem) {
1766 // REALLOCATION MODE
1767 // Calculate pointer to the end of the memory pool. It is
1768 // assumed that pPool + uPoolSize won't wrap around by
1769 // assuming the caller won't pass a pool buffer in that is
1770 // not in legitimate memory space.
1771 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1772
1773 // Check that the pointer for reallocation is in the range of the
1774 // pool. This also makes sure that pointer math further down
1775 // doesn't wrap under or over.
1776 if(pMem >= pPool && pMem < pPoolEnd) {
1777 // Offset to start of chunk for reallocation. This won't
1778 // wrap under because of check that pMem >= pPool. Cast
1779 // is safe because the pool is always less than UINT32_MAX
1780 // because of check in QCBORDecode_SetMemPool().
1781 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1782
1783 // Check to see if the allocation will fit. uPoolSize -
1784 // uMemOffset will not wrap under because of check that
1785 // pMem is in the range of the uPoolSize by check above.
1786 if(uNewSize <= uPoolSize - uMemOffset) {
1787 ReturnValue.ptr = pMem;
1788 ReturnValue.len = uNewSize;
1789
1790 // Addition won't wrap around over because uNewSize was
1791 // checked to be sure it is less than the pool size.
1792 uFreeOffset = uMemOffset + uNewSize32;
1793 }
1794 }
1795 } else {
1796 // ALLOCATION MODE
1797 // uPoolSize - uFreeOffset will not underflow because this
1798 // pool implementation makes sure uFreeOffset is always
1799 // smaller than uPoolSize through this check here and
1800 // reallocation case.
1801 if(uNewSize <= uPoolSize - uFreeOffset) {
1802 ReturnValue.len = uNewSize;
1803 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001804 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001805 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001806 }
1807 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001808 if(pMem) {
1809 // FREE MODE
1810 // Cast is safe because of limit on pool size in
1811 // QCBORDecode_SetMemPool()
1812 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1813 } else {
1814 // DESTRUCT MODE
1815 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001816 }
1817 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001818
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001819 UsefulBuf Pool = {pPool, uPoolSize};
1820 MemPool_Pack(Pool, uFreeOffset);
1821
1822Done:
1823 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001824}
1825
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001826
Laurence Lundbladef6531662018-12-04 10:42:22 +09001827/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001828 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09001829 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001830QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1831 UsefulBuf Pool,
1832 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001833{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001834 // The pool size and free mem offset are packed into the beginning
1835 // of the pool memory. This compile time check make sure the
1836 // constant in the header is correct. This check should optimize
1837 // down to nothing.
1838 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001839 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001840 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001841
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001842 // The pool size and free offset packed in to the beginning of pool
1843 // memory are only 32-bits. This check will optimize out on 32-bit
1844 // machines.
1845 if(Pool.len > UINT32_MAX) {
1846 return QCBOR_ERR_BUFFER_TOO_LARGE;
1847 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001848
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001849 // This checks that the pool buffer given is big enough.
1850 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1851 return QCBOR_ERR_BUFFER_TOO_SMALL;
1852 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001853
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001854 pMe->StringAllocator.pfAllocator = MemPool_Function;
1855 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1856 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001857
Laurence Lundblade30816f22018-11-10 13:40:22 +07001858 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001859}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001860
Laurence Lundblade1341c592020-04-11 14:19:05 -07001861#include <stdio.h>
1862void printdecode(QCBORDecodeContext *pMe, const char *szName)
1863{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001864 printf("---%s--%d--%d--\nLevel Count Type Offset SaveCount MapMode\n",
1865 szName,
1866 (uint32_t)pMe->InBuf.cursor,
1867 (uint32_t)pMe->InBuf.UB.len);
1868/* for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
1869 if(&(pMe->nesting.pMapsAndArrays[i]) > pMe->nesting.pCurrent) {
1870 break;
1871 }
1872 printf(" %2d %5d %s %6u %2d %d\n",
Laurence Lundblade1341c592020-04-11 14:19:05 -07001873 i,
1874 pMe->nesting.pMapsAndArrays[i].uCount,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001875 pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_MAP ? " map" :
1876 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_ARRAY ? "array" :
1877 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_NONE ? " none" : "?????")),
Laurence Lundblade1341c592020-04-11 14:19:05 -07001878 pMe->nesting.pMapsAndArrays[i].uOffset,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001879 pMe->nesting.pMapsAndArrays[i].uSaveCount,
1880 pMe->nesting.pMapsAndArrays[i].uMapMode
Laurence Lundblade1341c592020-04-11 14:19:05 -07001881 );
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001882
Laurence Lundblade1341c592020-04-11 14:19:05 -07001883 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001884 printf("\n"); */
Laurence Lundblade1341c592020-04-11 14:19:05 -07001885}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001886
1887
1888/*
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001889 *
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001890 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001891static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001892ConsumeItem(QCBORDecodeContext *pMe,
1893 const QCBORItem *pItemToConsume,
1894 uint_fast8_t *puNextNestLevel)
1895{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001896 QCBORError nReturn;
1897 QCBORItem Item;
1898
1899 printdecode(pMe, "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001900
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001901 if(IsMapOrArray(pItemToConsume->uDataType)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001902 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001903
Laurence Lundblade1341c592020-04-11 14:19:05 -07001904 /* This works for definite and indefinite length
1905 * maps and arrays by using the nesting level
1906 */
1907 do {
1908 nReturn = QCBORDecode_GetNext(pMe, &Item);
1909 if(nReturn != QCBOR_SUCCESS) {
1910 goto Done;
1911 }
1912 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001913
Laurence Lundblade1341c592020-04-11 14:19:05 -07001914 if(puNextNestLevel != NULL) {
1915 *puNextNestLevel = Item.uNextNestLevel;
1916 }
1917 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001918
Laurence Lundblade1341c592020-04-11 14:19:05 -07001919 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001920 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07001921 if(puNextNestLevel != NULL) {
1922 /* Just pass the nesting level through */
1923 *puNextNestLevel = pItemToConsume->uNextNestLevel;
1924 }
1925 nReturn = QCBOR_SUCCESS;
1926 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001927
1928Done:
1929 return nReturn;
1930}
1931
1932
Laurence Lundblade1341c592020-04-11 14:19:05 -07001933/* Return true if the labels in Item1 and Item2 are the same.
1934 Works only for integer and string labels. Returns false
1935 for any other type. */
1936static inline bool
1937MatchLabel(QCBORItem Item1, QCBORItem Item2)
1938{
1939 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
1940 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
1941 return true;
1942 }
1943 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001944 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001945 return true;
1946 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001947 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
1948 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
1949 return true;
1950 }
1951 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
1952 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
1953 return true;
1954 }
1955 }
1956
Laurence Lundblade1341c592020-04-11 14:19:05 -07001957 /* Other label types are never matched */
1958 return false;
1959}
1960
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001961static inline bool
1962MatchType(QCBORItem Item1, QCBORItem Item2)
1963{
1964 if(Item1.uDataType == Item2.uDataType) {
1965 return true;
1966 } else if(Item1.uLabelType == QCBOR_TYPE_ANY) {
1967 return true;
1968 } else if(Item2.uLabelType == QCBOR_TYPE_ANY) {
1969 return true;
1970 }
1971
1972 /* Other label types are never matched */
1973 return false;
1974}
1975
1976
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001977/*
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001978 On input pItemArray contains a list of labels and data types
1979 of items to be found.
1980
1981 On output the fully retrieved items are filled in with
1982 values and such. The label was matched, so it never changes.
1983
1984 If an item was not found, its data type is set to none.
1985
1986 TODO: type in and out is not right.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001987 */
1988QCBORError
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001989GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemArray, size_t *puOffset, size_t *puEndOffset)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001990{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001991 QCBORError nReturn;
1992
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001993 if(!DecodeNesting_InMapMode(&(pMe->nesting))) {
1994 return QCBOR_ERR_NOT_ENTERED;
Laurence Lundblade1341c592020-04-11 14:19:05 -07001995 }
1996
Laurence Lundblade1341c592020-04-11 14:19:05 -07001997 QCBORDecodeNesting N = pMe->nesting;
1998
1999 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
2000 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2001 }
2002
2003 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2004
2005 /* Loop over all the items in the map. They could be
2006 * deeply nested and this should handle both definite
2007 * and indefinite length maps and arrays, so this
2008 * adds some complexity. */
2009 const uint8_t uMapNestLevel = DecodeNesting_GetLevel(&(pMe->nesting));
2010
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002011 uint_fast8_t uNextNestLevel;
2012
2013 uint64_t uFound = 0;
2014
2015 do {
2016 /* Remember offset because sometims we have to return it */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002017 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002018
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002019 /* Get the item */
2020 QCBORItem Item;
2021 nReturn = QCBORDecode_GetNext(pMe, &Item);
2022 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002023 /* Got non-well-formed CBOR */
2024 goto Done;
2025 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002026
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002027 /* See if item has one of the labels that are of interest */
2028 int i;
2029 QCBORItem *pIterator;
2030 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002031 if(MatchLabel(Item, *pIterator)) {
2032 // A label match has been found
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002033 if(uFound & (0x01ULL << i)) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002034 nReturn = QCBOR_ERR_DUPLICATE_LABEL;
2035 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002036 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002037 if(!MatchType(Item, *pIterator)) {
2038 nReturn = QCBOR_ERR_UNEXPECTED_TYPE;
2039 goto Done;
2040 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002041
2042 /* Successful match. Return the item. */
2043 *pIterator = Item;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002044 uFound |= 0x01ULL << i;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002045 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002046 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002047 }
2048 }
2049 }
2050
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002051 /* Consume the item whether matched or not. This
2052 does th work of traversing maps and array and
2053 everything in them. In this loop only the
2054 items at the current nesting level are examined
2055 to match the labels. */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002056 nReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2057 if(nReturn) {
2058 goto Done;
2059 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002060
2061 } while (uNextNestLevel >= uMapNestLevel);
2062
2063
2064 nReturn = QCBOR_SUCCESS;
2065
2066 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
2067 // Cast OK because encoded CBOR is limited to UINT32_MAX
2068 pMe->uMapEndOffset = (uint32_t)uEndOffset;
2069 // TODO: is zero *puOffset OK?
2070 if(puEndOffset) {
2071 *puEndOffset = uEndOffset;
2072 }
2073
2074 /* Mark all the ones not found */
2075 int i;
2076 QCBORItem *pIterator;
2077 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
2078 if(!(uFound & (0x01ULL << i))) {
2079 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002080 }
2081 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002082
2083Done:
Laurence Lundblade1341c592020-04-11 14:19:05 -07002084 pMe->nesting = N;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002085
Laurence Lundblade1341c592020-04-11 14:19:05 -07002086 return nReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002087}
2088
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002089
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002090void QCBORDecode_ExitMap(QCBORDecodeContext *pMe)
2091{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002092 size_t uEndOffset;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002093
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002094/*
Laurence Lundblade1341c592020-04-11 14:19:05 -07002095 if(pMe->uMapEndOffset) {
2096 uEndOffset = pMe->uMapEndOffset;
2097 // It is only valid once.
2098 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002099 } else { */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002100 QCBORItem Dummy;
2101
2102 Dummy.uLabelType = QCBOR_TYPE_NONE;
2103
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002104 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002105
2106 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002107// }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002108
2109 printdecode(pMe, "start exit");
2110 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2111
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002112 DecodeNesting_Exit(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002113 printdecode(pMe, "end exit");
2114
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002115}
2116
2117
2118QCBORError QCBORDecode_GetItemInMap(QCBORDecodeContext *pMe,
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002119 int64_t nLabel,
2120 uint8_t uQcborType,
2121 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002122{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002123 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002124
Laurence Lundblade1341c592020-04-11 14:19:05 -07002125 One[0].uLabelType = QCBOR_TYPE_INT64;
2126 One[0].label.int64 = nLabel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002127 One[0].uDataType = uQcborType;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002128 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2129
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002130 QCBORError nReturn = GetItemsInMap(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002131 if(nReturn) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002132 return nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002133 }
2134
2135 if(One[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002136 return QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002137 }
2138
2139 *pItem = One[0];
2140
2141 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002142}
2143
2144
2145QCBORError QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002146 const char *szLabel,
2147 uint8_t uQcborType,
2148 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002149{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002150 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002151
Laurence Lundblade1341c592020-04-11 14:19:05 -07002152 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2153 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002154 One[0].uDataType = uQcborType;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002155 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2156
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002157 QCBORError nReturn = GetItemsInMap(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002158 if(nReturn) {
2159 return nReturn;
2160 }
2161
2162 if(One[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002163 return QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002164 }
2165
2166 *pItem = One[0];
2167
2168 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002169}
2170
2171
Laurence Lundblade1341c592020-04-11 14:19:05 -07002172
Laurence Lundblade1341c592020-04-11 14:19:05 -07002173
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002174static int FinishEnter(QCBORDecodeContext *pMe, size_t uOffset)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002175{
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002176 /* Seek to the data item that is the map or array */
2177 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2178
2179 /* Skip the data item that is the map or array */
2180 QCBORItem MapToEnter;
2181 // TODO: check error
2182 QCBORDecode_GetNext(pMe, &MapToEnter);
2183
2184 /* Enter map mode with an offset that is the first item
2185 in the map or array. */
2186 // TODO: what if map or array is empty?
2187 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
2188
2189
2190 printdecode(pMe, "Entered Map in Map");
2191
2192 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002193}
2194
2195
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002196QCBORError QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002197{
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002198 /* Use GetItemsInMap to find the map by label, including the
2199 byte offset of it. */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002200 QCBORItem One[2];
Laurence Lundblade1341c592020-04-11 14:19:05 -07002201 One[0].uLabelType = QCBOR_TYPE_INT64;
2202 One[0].label.int64 = nLabel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002203 One[0].uDataType = QCBOR_TYPE_MAP;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002204 One[1].uLabelType = QCBOR_TYPE_NONE;
2205
2206 size_t uOffset;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002207 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002208 if(nReturn) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002209 return nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002210 }
2211
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002212 /* The map to enter was found, now finish of entering it. */
2213 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002214
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002215 // TODO: error code?
Laurence Lundblade1341c592020-04-11 14:19:05 -07002216 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002217}
2218
2219
2220QCBORError QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2221{
2222 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002223
Laurence Lundblade1341c592020-04-11 14:19:05 -07002224 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2225 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002226 One[0].uDataType = QCBOR_TYPE_MAP;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002227 One[1].uLabelType = QCBOR_TYPE_NONE;
2228
2229 size_t uOffset;
2230
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002231 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002232
2233 if(nReturn) {
2234 return nReturn;
2235 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002236
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002237 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002238
2239 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002240}
2241
2242
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002243QCBORError QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002244{
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002245 QCBORItem One[2];
2246
2247 One[0].uLabelType = QCBOR_TYPE_INT64;
2248 One[0].label.int64 = nLabel;
2249 One[0].uDataType = QCBOR_TYPE_ARRAY;
2250 One[1].uLabelType = QCBOR_TYPE_NONE;
2251
2252 size_t uOffset;
2253
2254 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
2255
2256 if(nReturn != QCBOR_SUCCESS) {
2257 return nReturn;
2258 }
2259
2260 FinishEnter(pMe, uOffset);
2261
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002262 return 0;
2263}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002264
Laurence Lundblade1341c592020-04-11 14:19:05 -07002265
2266QCBORError QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2267{
2268 QCBORItem One[2];
2269
2270 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2271 One[0].label.string = UsefulBuf_FromSZ(szLabel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002272 One[0].uDataType = QCBOR_TYPE_ARRAY;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002273 One[1].uLabelType = QCBOR_TYPE_NONE;
2274
2275 size_t uOffset;
2276
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002277 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002278
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002279 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002280 return nReturn;
2281 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002282
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002283 FinishEnter(pMe, uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002284
2285 return 0;
2286}
2287
2288
2289
2290
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002291
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002292/* Next item must be map or this generates an error */
2293QCBORError QCBORDecode_EnterMap(QCBORDecodeContext *pMe)
2294{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002295 QCBORItem Item;
2296 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002297
2298 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002299 nReturn = QCBORDecode_GetNext(pMe, &Item);
2300 if(nReturn != QCBOR_SUCCESS) {
2301 return nReturn;
2302 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002303 if(Item.uDataType != QCBOR_TYPE_MAP) {
2304 return QCBOR_ERR_UNEXPECTED_TYPE;
2305 }
2306
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002307 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002308
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002309 printdecode(pMe, "EnterMapDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002310
Laurence Lundblade1341c592020-04-11 14:19:05 -07002311 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002312}
2313
2314
2315
2316QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2317{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002318 return GetItemsInMap(pCtx, pItemList, NULL, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002319}
2320
2321
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002322
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002323
2324
Laurence Lundblade1341c592020-04-11 14:19:05 -07002325void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002326{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002327 // TODO: check for map mode
2328 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2329 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2330}
2331
2332
2333QCBORError QCBORDecode_EnterArray(QCBORDecodeContext *pMe)
2334{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002335 QCBORItem Item;
2336 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002337
2338 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002339 nReturn = QCBORDecode_GetNext(pMe, &Item);
2340 if(nReturn != QCBOR_SUCCESS) {
2341 return nReturn;
2342 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002343 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
2344 return QCBOR_ERR_UNEXPECTED_TYPE;
2345 }
2346
2347 printdecode(pMe, "EnterArray");
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002348
2349 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002350
2351 return QCBOR_SUCCESS;
2352}
2353
2354
2355void QCBORDecode_ExitArray(QCBORDecodeContext *pMe)
2356{
2357 // TODO: make sure we have entered an array
2358 // TODO: combine with code for map? It is the same so far.
2359 size_t uEndOffset;
2360
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002361 /* if(pMe->uMapEndOffset) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002362 uEndOffset = pMe->uMapEndOffset;
2363 // It is only valid once.
2364 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002365 } else {*/
Laurence Lundblade1341c592020-04-11 14:19:05 -07002366 QCBORItem Dummy;
2367
2368 Dummy.uLabelType = QCBOR_TYPE_NONE;
2369
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002370 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002371
2372 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002373 //}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002374
Laurence Lundblade1341c592020-04-11 14:19:05 -07002375 printdecode(pMe, "start exit");
2376 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2377
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002378 DecodeNesting_Exit(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002379 printdecode(pMe, "end exit");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002380}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002381
Laurence Lundbladee6430642020-03-14 21:15:44 -07002382
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002383void QCBORDecode_GetIntInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, int64_t *pInt)
2384{
2385 // TODO: error handling
2386 QCBORItem Item;
2387 QCBORDecode_GetItemInMapSZ(pMe,szLabel, QCBOR_TYPE_INT64, &Item);
2388 *pInt = Item.val.int64;
2389}
2390
2391void QCBORDecode_GetBstrInMapN(QCBORDecodeContext *pMe, int64_t nLabel, UsefulBufC *pBstr)
2392{
2393 // TODO: error handling
2394 QCBORItem Item;
2395 QCBORDecode_GetItemInMap(pMe, nLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2396 *pBstr = Item.val.string;
2397}
2398
2399void QCBORDecode_GetBstrInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2400{
2401 // TODO: error handling
2402 QCBORItem Item;
2403 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2404 *pBstr = Item.val.string;
2405}
2406
2407void QCBORDecode_GetTextInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2408{
2409 // TODO: error handling
2410 QCBORItem Item;
2411 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_TEXT_STRING, &Item);
2412 *pBstr = Item.val.string;
2413}
2414
Laurence Lundbladee6430642020-03-14 21:15:44 -07002415
Laurence Lundbladec4537442020-04-14 18:53:22 -07002416void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002417{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002418 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002419 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07002420 return;
2421 }
2422
Laurence Lundbladec4537442020-04-14 18:53:22 -07002423 QCBORError nError;
2424 QCBORItem Item;
2425
2426 nError = QCBORDecode_GetNext(pMe, &Item);
2427 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002428 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002429 return;
2430 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002431
2432 switch(Item.uDataType) {
2433 case QCBOR_TYPE_TRUE:
2434 *pValue = true;
2435 break;
2436
2437 case QCBOR_TYPE_FALSE:
2438 *pValue = false;
2439 break;
2440
2441 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002442 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002443 break;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002444 }
2445}
2446
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002447#if 0
2448// TODO: fix this
Laurence Lundbladee6430642020-03-14 21:15:44 -07002449/* Types of text strings
2450 * Plain, b64, b64url, URI, regex, MIME Text
2451 * One function for each with options to expect plain?
2452 * One function for all so you can say what you want?
Laurence Lundbladec4537442020-04-14 18:53:22 -07002453 *
2454 * A label is expected if pLabel is not NULL.
Laurence Lundbladee6430642020-03-14 21:15:44 -07002455 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002456void QCBORDecode_GetTextFoo(QCBORDecodeContext *pMe, QCBORLabel *pLabel, UsefulBufC *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002457{
2458 QCBORItem Item;
2459 QCBORError nError;
2460
2461 nError = QCBORDecode_GetNext(pMe, &Item);
2462 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002463 pMe->uLastError = nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002464 return;
2465 }
2466
Laurence Lundbladec4537442020-04-14 18:53:22 -07002467 if(pLabel != NULL) {
2468 if(Item.uLabelType == QCBOR_TYPE_NONE) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002469 pMe->uLastError = 9; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07002470 return;
2471 } else {
2472 // TODO: what about label allocation?
2473 pLabel->uLabelType = Item.uLabelType;
2474 pLabel->label.xx = Item.label.int64; // TOOD: figure out assignment
2475 }
2476 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002477
2478 switch(Item.uDataType) {
2479 case QCBOR_TYPE_TEXT_STRING:
2480 *pValue = Item.val.string;
2481 break;
2482
2483 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002484 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002485 }
2486}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002487#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002488
2489
Laurence Lundbladec4537442020-04-14 18:53:22 -07002490/*
2491 Options for MIME data, CBOR, positive big num, negative big num ??
2492 */
2493void QCBORDecode_GetStringInternal(QCBORDecodeContext *pMe, UsefulBufC *pValue, uint8_t uType)
2494{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002495 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002496 // Already in error state, do nothing
2497 return;
2498 }
2499
2500 QCBORError nError;
2501 QCBORItem Item;
2502
2503 nError = QCBORDecode_GetNext(pMe, &Item);
2504 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002505 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002506 return;
2507 }
2508
2509 if(Item.uDataType == uType) {
2510 *pValue = Item.val.string;
2511 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002512 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002513 }
2514}
2515
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002516void QCBORDecode_GetBytes(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002517{
2518 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_BYTE_STRING);
2519}
2520
2521
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002522void QCBORDecode_GetText(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002523{
2524 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_TEXT_STRING);
2525}
2526
2527
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002528void QCBORDecode_GetPosBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002529{
2530 // TODO: do these have to be tagged?
2531 // Probably should allow tagged or untagged, but not wrong-tagged
2532 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_POSBIGNUM);
2533}
2534
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002535void QCBORDecode_GetNegBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002536{
2537 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_NEGBIGNUM);
2538}
2539
2540
2541
Laurence Lundbladee6430642020-03-14 21:15:44 -07002542
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002543typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002544
2545
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002546// The main exponentiator that works on only positive numbers
2547static QCBORError Exponentitate10UU(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002548{
2549 uint64_t uResult;
2550
2551 uResult = uMantissa;
2552
2553 /* This loop will run a maximum of 19 times because
2554 * UINT64_MAX < 10 ^^ 19. More than that will cause
2555 * exit with the overflow error
2556 */
2557 while(nExponent > 0) {
2558 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002559 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladec4537442020-04-14 18:53:22 -07002560 }
2561 uResult = uResult * 10;
2562 nExponent--;
2563 }
2564
2565 while(nExponent < 0 ) {
2566 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002567 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
Laurence Lundbladec4537442020-04-14 18:53:22 -07002568 }
2569 uResult = uResult / 10;
2570 nExponent--;
2571 }
2572
2573 *puResult = uResult;
2574
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002575 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002576}
2577
2578
Laurence Lundbladee6430642020-03-14 21:15:44 -07002579/* Convert a decimal fraction to an int64_t without using
2580 floating point or math libraries. Most decimal fractions
2581 will not fit in an int64_t and this will error out with
2582 under or overflow
2583 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002584static QCBORError Exponentitate2UU(uint64_t nMantissa, int64_t nExponent, uint64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002585{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002586 uint64_t nResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002587
2588 nResult = nMantissa;
2589
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002590 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07002591 * INT64_MAX < 2^31. More than that will cause
2592 * exist with the overflow error
2593 */
2594 while(nExponent > 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002595 if(nResult > UINT64_MAX >> 1) {
2596 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07002597 }
2598 nResult = nResult << 1;
2599 nExponent--;
2600 }
2601
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002602 while(nExponent < 0 ) {
2603 if(nResult == 0) {
2604 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
2605 }
2606 nResult = nResult >> 1;
2607 nExponent--;
2608 }
2609
Laurence Lundbladee6430642020-03-14 21:15:44 -07002610 *pnResult = nResult;
2611
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002612 return QCBOR_SUCCESS;
2613}
2614
2615
2616static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2617{
2618 uint64_t uResult;
2619
2620 // Take the absolute value of the mantissa
2621 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
2622
2623 // Do the exponentiation of the positive mantissa
2624 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
2625 if(uReturn) {
2626 return uReturn;
2627 }
2628
2629 // Error out if too large on the plus side for an int64_t
2630 if(uResult > INT64_MAX) {
2631 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2632 }
2633
2634 // Error out if too large on the negative side for an int64_t
2635 if(uResult < (uint64_t)INT64_MAX+1) {
2636 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
2637 of INT64_MIN. This assumes two's compliment representation where
2638 INT64_MIN is one increment farther from 0 than INT64_MAX.
2639 Trying to write -INT64_MIN doesn't work to get this because the
2640 compiler tries to work with an int64_t which can't represent
2641 -INT64_MIN.
2642 */
2643 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2644 }
2645
2646 // Casts are safe because of checks above
2647 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
2648
2649 return QCBOR_SUCCESS;
2650}
2651
2652
2653static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
2654{
2655 if(nMantissa < 0) {
2656 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
2657 }
2658
2659 // Cast to unsigned is OK because of check for negative
2660 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
2661 // Exponentiation is straight forward
2662 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
2663}
2664
2665
2666// TODO: use this or get rid of it
2667QCBORError ExponentitateUN(uint64_t uMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2668{
2669 uint64_t uResult;
2670
2671 QCBORError uR;
2672
2673 uR = (*pfExp)(uMantissa, nExponent, &uResult);
2674 if(uR) {
2675 return uR;
2676 }
2677
2678 if(uResult > INT64_MAX) {
2679 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2680 }
2681
2682 // Cast is OK because of check above
2683 *pnResult = (int64_t)uResult;
2684
2685 return QCBOR_SUCCESS;
2686}
2687
2688
2689
2690
2691#include <math.h>
2692/*
2693static inline uint8_t Exponentitate10F(uint64_t uMantissa, int64_t nExponent, double *pfResult)
2694{
2695 // TODO: checkout exceptions; what is HUGE_VAL?
2696 *pfResult = pow((double)10, (double)nExponent) * (double)uMantissa;
2697
2698 //if(*pfResult == HUGE_VAL)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002699 return 0;
2700}
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002701*/
2702
2703
2704
2705
2706
Laurence Lundbladee6430642020-03-14 21:15:44 -07002707
2708/*
2709 A) bignum is positive
2710 A1) output is signed INT64_MAX
2711 A2) output is unsigned UINT64_MAX
2712 B) bignum is negative
2713 B1) output is signed INT64_MAX
2714 B2) output is unsigned error
2715 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002716static inline QCBORError ConvertBigNum(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002717{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002718 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002719
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002720 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002721 const uint8_t *pByte = BigNum.ptr;
2722 size_t uLen = BigNum.len;
2723 while(uLen--) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002724 if(uResult > uMax >> 8) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002725 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002726 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002727 uResult = (uResult << 8) + *pByte;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002728 }
2729
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002730 *pResult = uResult;
2731 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002732}
2733
Laurence Lundbladec4537442020-04-14 18:53:22 -07002734
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002735#if 0
2736static inline QCBORError ConvertBigNumToDouble(const UsefulBufC BigNum, uint64_t uMax, double *pResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002737{
2738 double nResult;
2739
2740 nResult = 0;
2741 const uint8_t *pByte = BigNum.ptr;
2742 size_t uLen = BigNum.len;
2743 /* This will overflow and become the float value INFINITY if the number
2744 is too large to fit. No error will be logged.
2745 TODO: should an error be logged? */
2746 while(uLen--) {
2747 nResult = (nResult * 256) + *pByte;
2748 }
2749
2750 *pResult = nResult;
2751 return 0;
2752}
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002753#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07002754
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002755static inline QCBORError ConvertPositiveBigNumToUnSigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002756{
2757 return ConvertBigNum(BigNum, UINT64_MAX, pResult);
2758}
2759
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002760static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002761{
2762 uint64_t uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002763 QCBORError n = ConvertBigNum(BigNum, INT64_MAX, &uResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002764 if(n) {
2765 return n;
2766 }
2767 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2768 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002769 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002770}
2771
2772
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002773static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002774{
2775 uint64_t uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002776 QCBORError n = ConvertBigNum(BigNum, INT64_MAX-1, &uResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002777 if(n) {
2778 return n;
2779 }
2780 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2781 *pResult = -(int64_t)uResult;
2782 return 0;
2783}
2784
Laurence Lundbladec4537442020-04-14 18:53:22 -07002785// No function to convert a negative bignum to unsigned; it is an error
2786
2787
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002788#if 0
2789static inline int ConvertXYZ(const UsefulBufC Mantissa, int64_t nExponent, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002790{
2791 int64_t nMantissa;
2792
2793 int xx = ConvertPositiveBigNumToSigned(Mantissa, &nMantissa);
2794 if(xx) {
2795 return xx;
2796 }
2797
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002798 return ExponentiateNN(nMantissa, nExponent, pResult, &Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002799}
2800
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002801#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002802
2803
Laurence Lundbladee6430642020-03-14 21:15:44 -07002804
Laurence Lundbladec4537442020-04-14 18:53:22 -07002805
2806/*
2807 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2808 a big float, a decimal fraction or a big num. Conversion will be dones as
2809 expected. Some cases will error out with under or over flow.
2810 */
2811void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue, QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002812{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002813 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002814 return;
2815 }
2816
Laurence Lundbladee6430642020-03-14 21:15:44 -07002817 QCBORItem Item;
2818 QCBORError nError;
2819
2820 nError = QCBORDecode_GetNext(pMe, &Item);
2821 if(nError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002822 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002823 return;
2824 }
2825
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002826 if(pItem) {
2827 *pItem = Item;
2828 }
2829
Laurence Lundbladee6430642020-03-14 21:15:44 -07002830 switch(Item.uDataType) {
2831 case QCBOR_TYPE_FLOAT:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002832 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002833 // TODO: what about under/overflow here?
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002834 // Invokes the floating-point HW and/or compiler-added libraries
Laurence Lundbladee6430642020-03-14 21:15:44 -07002835 *pValue = (int64_t)Item.val.dfnum;
2836 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002837 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002838 }
2839 break;
2840
2841 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002842 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002843 *pValue = Item.val.int64;
2844 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002845 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002846 }
2847 break;
2848
2849 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002850 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002851 if(Item.val.uint64 < INT64_MAX) {
2852 *pValue = Item.val.int64;
2853 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002854 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002855 }
2856 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002857 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002858 }
2859 break;
2860
Laurence Lundbladec4537442020-04-14 18:53:22 -07002861 default:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002862 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002863 }
2864}
2865
2866/* This works for signed, unsigned and float */
2867void QCBORDecode_GetInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2868{
2869 QCBORItem Item;
2870 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2871}
2872
2873
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002874// TODO make this inline
2875void QCBORDecode_GetInt64(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2876{
2877 QCBORDecode_GetInt64Convert(pMe, QCBOR_TYPE_INT64, pValue);
2878}
2879
2880
Laurence Lundbladec4537442020-04-14 18:53:22 -07002881
2882/*
2883 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2884 a big float, a decimal fraction or a big num. Conversion will be dones as
2885 expected. Some cases will error out with under or over flow.
2886 */
2887void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2888{
2889 QCBORItem Item;
2890
2891 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2892
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002893 if(pMe->uLastError == QCBOR_SUCCESS) {
2894 // The above conversion succeeded
2895 return;
2896 }
2897
2898 if(pMe->uLastError != QCBOR_SUCCESS && pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
2899 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07002900 return;
2901 }
2902
2903 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002904
2905 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002906 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002907 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002908 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002909 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002910 }
2911 break;
2912
2913 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002914 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002915 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002916 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002917 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002918 }
2919 break;
2920
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002921#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2922 case QCBOR_TYPE_DECIMAL_FRACTION:
2923 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002924 pMe->uLastError = (uint8_t)ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002925 Item.val.expAndMantissa.nExponent,
2926 pValue,
2927 &Exponentitate10UU);
2928 } else {
2929 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2930 }
2931 break;
2932
2933 case QCBOR_TYPE_BIGFLOAT:
2934 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002935 pMe->uLastError = (uint8_t)ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002936 Item.val.expAndMantissa.nExponent,
2937 pValue,
2938 &Exponentitate2UU);
2939 } else {
2940 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2941 }
2942 break;
2943
2944
Laurence Lundbladee6430642020-03-14 21:15:44 -07002945 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002946 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002947 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002948 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002949 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002950 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002951 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002952 pValue,
2953 &Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002954 }
2955 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002956 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002957 }
2958 break;
2959
2960 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002961 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002962 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002963 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002964 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002965 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002966 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002967 pValue,
2968 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002969 }
2970 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002971 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002972 }
2973 break;
2974
2975 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002976 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002977 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002978 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002979 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002980 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002981 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002982 pValue,
2983 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002984 }
2985 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002986 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002987 }
2988 break;
2989
2990 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002991 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002992 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002993 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002994 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002995 pMe->uLastError = (uint8_t)ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002996 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002997 pValue,
2998 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002999 }
3000 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003001 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003002 }
3003 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003004
3005 default:
3006 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
3007#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07003008 }
3009}
3010
Laurence Lundbladec4537442020-04-14 18:53:22 -07003011
3012
3013void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue, QCBORItem *pItem)
3014{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003015 if(pMe->uLastError != QCBOR_SUCCESS) {
3016 return;
3017 }
3018
Laurence Lundbladec4537442020-04-14 18:53:22 -07003019 QCBORItem Item;
3020 QCBORError nError;
3021
3022 nError = QCBORDecode_GetNext(pMe, &Item);
3023 if(nError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003024 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003025 return;
3026 }
3027
3028 switch(Item.uDataType) {
3029 case QCBOR_TYPE_FLOAT:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003030 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003031 if(Item.val.dfnum >= 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003032 // TODO: over/underflow
Laurence Lundbladec4537442020-04-14 18:53:22 -07003033 *pValue = (uint64_t)Item.val.dfnum;
3034 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003035 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003036 }
3037 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003038 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003039 }
3040 break;
3041
3042 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003043 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003044 if(Item.val.int64 >= 0) {
3045 *pValue = (uint64_t)Item.val.int64;
3046 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003047 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003048 }
3049 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003050 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003051 }
3052 break;
3053
3054 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003055 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003056 *pValue = Item.val.uint64;
3057 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003058 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003059 }
3060 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003061
3062 default:
3063 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003064 }
3065}
3066
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003067
3068/* This works for signed, unsigned and float */
3069void QCBORDecode_GetUInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003070{
3071 QCBORItem Item;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003072 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
3073}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003074
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003075
3076// TODO make this inline
3077void QCBORDecode_GetUInt64(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
3078{
3079 QCBORDecode_GetUInt64Convert(pMe, QCBOR_TYPE_UINT64, pValue);
3080}
3081
3082
3083
3084
3085void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
3086{
3087 QCBORItem Item;
3088
3089 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
3090
3091 if(pMe->uLastError != QCBOR_SUCCESS && pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003092 return;
3093 }
3094
Laurence Lundbladee6430642020-03-14 21:15:44 -07003095 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003096
3097 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003098 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003099 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToUnSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003100 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003101 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003102 }
3103 break;
3104
3105 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003106 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003107 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToUnSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003108 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003109 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003110 }
3111 break;
3112
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003113#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3114
3115 case QCBOR_TYPE_DECIMAL_FRACTION:
3116 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003117 pMe->uLastError = (uint8_t)ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003118 Item.val.expAndMantissa.nExponent,
3119 pValue,
3120 Exponentitate10UU);
3121 } else {
3122 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
3123 }
3124 break;
3125
3126 case QCBOR_TYPE_BIGFLOAT:
3127 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003128 pMe->uLastError = (uint8_t)ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003129 Item.val.expAndMantissa.nExponent,
3130 pValue,
3131 Exponentitate2UU);
3132 } else {
3133 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
3134 }
3135 break;
3136
3137
3138
Laurence Lundbladee6430642020-03-14 21:15:44 -07003139 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003140 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003141 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003142 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003143 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003144 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003145 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003146 pValue,
3147 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003148 }
3149 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003150 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003151 }
3152 break;
3153
3154 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003155 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003156 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003157 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003158 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003159 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003160 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003161 pValue,
3162 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003163 }
3164 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003165 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003166 }
3167 break;
3168
3169 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003170 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003171 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003172 pMe->uLastError = (uint8_t)ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003173 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003174 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003175 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003176 pValue,
3177 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003178 }
3179 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003180 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003181 }
3182 break;
3183
3184 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003185 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003186 int64_t nMantissa;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003187 pMe->uLastError = (uint8_t)ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003188 if(!pMe->uLastError) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003189 pMe->uLastError = (uint8_t)ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003190 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003191 pValue,
3192 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003193 }
3194 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003195 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003196 }
3197 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003198#endif
3199 default:
3200 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003201 }
3202}
3203
Laurence Lundbladec4537442020-04-14 18:53:22 -07003204
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003205
3206#if 0
Laurence Lundbladec4537442020-04-14 18:53:22 -07003207/*
3208
3209 Convert from bignums,
3210
3211 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003212void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003213{
3214 /* the same range of conversions */
3215
Laurence Lundbladec4537442020-04-14 18:53:22 -07003216 /* Conversion from bignums, decimal fractions and such will be interesting */
3217
3218 QCBORItem Item;
3219 QCBORError nError;
3220
3221 nError = QCBORDecode_GetNext(pMe, &Item);
3222 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003223 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003224 return;
3225 }
3226
Laurence Lundbladec4537442020-04-14 18:53:22 -07003227
3228 switch(Item.uDataType) {
3229 case QCBOR_TYPE_FLOAT:
3230 if(uOptions & QCBOR_DECODE_TYPE_FLOAT) {
3231 *pValue = Item.val.dfnum;
3232 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003233 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003234 }
3235 break;
3236
3237 case QCBOR_TYPE_INT64:
3238 if(uOptions & QCBOR_DECODE_TYPE_INT64) {
3239 // TODO: how does this work?
3240 *pValue = (double)Item.val.int64;
3241 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003242 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003243 }
3244 break;
3245
3246 case QCBOR_TYPE_UINT64:
3247 if(uOptions & QCBOR_DECODE_TYPE_UINT64) {
3248 *pValue = (double)Item.val.uint64;
3249 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003250 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003251 }
3252 break;
3253
3254 case QCBOR_TYPE_DECIMAL_FRACTION:
3255 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003256 pMe->uLastError = Exponentitate10(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003257 Item.val.expAndMantissa.nExponent,
3258 pValue);
3259 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003260 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003261 }
3262 break;
3263
3264 case QCBOR_TYPE_BIGFLOAT:
3265 if(uOptions & QCBOR_DECODE_TYPE_BIGFLOAT) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003266 pMe->uLastError = Exponentitate2(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003267 Item.val.expAndMantissa.nExponent,
3268 pValue);
3269 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003270 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003271 }
3272 break;
3273
3274 case QCBOR_TYPE_POSBIGNUM:
3275 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003276 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003277 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003278 pMe->uLastError = 99;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003279 }
3280 break;
3281
3282 case QCBOR_TYPE_NEGBIGNUM:
3283 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003284 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003285 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003286 pMe->uLastError = 99;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003287 }
3288 break;
3289
3290 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3291 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3292 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003293 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3294 if(!pMe->uLastError) {
3295 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003296 Item.val.expAndMantissa.nExponent,
3297 pValue);
3298 }
3299 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003300 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003301 }
3302 break;
3303
3304 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3305 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3306 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003307 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3308 if(!pMe->uLastError) {
3309 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003310 Item.val.expAndMantissa.nExponent,
3311 pValue);
3312 }
3313 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003314 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003315 }
3316 break;
3317
3318 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3319 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3320 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003321 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3322 if(!pMe->uLastError) {
3323 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003324 Item.val.expAndMantissa.nExponent,
3325 pValue);
3326 }
3327 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003328 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003329 }
3330 break;
3331
3332 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3333 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3334 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003335 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3336 if(!pMe->uLastError) {
3337 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003338 Item.val.expAndMantissa.nExponent,
3339 pValue);
3340 }
3341 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003342 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003343 }
3344 break;
3345 }
3346
3347
3348
Laurence Lundbladee6430642020-03-14 21:15:44 -07003349}
3350
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003351#endif