blob: ff1516c46cec51fbeae7eb5adb58f9b20a15a246 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070035#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070036
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070037
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053038/*
39 This casts away the const-ness of a pointer, usually so it can be
40 freed or realloced.
41 */
42#define UNCONST_POINTER(ptr) ((void *)(ptr))
43
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070044
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070045
Laurence Lundbladeee851742020-01-08 08:37:05 -080046/*===========================================================================
47 DecodeNesting -- Functions for tracking array/map nesting when decoding
48
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080049 See qcbor/qcbor_decode.h for definition of the object
50 used here: QCBORDecodeNesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080051 ===========================================================================*/
52
Laurence Lundblade9c905e82020-04-25 11:31:38 -070053
54
55/*
56The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...)
57formed by intermediate nodes (arrays and maps). The cursor for the traversal
58 is the byte offset in the encoded input and a leaf counter for definite
59 length maps and arrays. Indefinite length maps and arrays are handled
60 by look ahead for the break.
61
62 The view presented to the caller has tags, labels and the chunks of
63 indefinite length strings aggregated into one decorated data item.
64
65The caller understands the nesting level in pre-order traversal by
66 the fact that a data item that is a map or array is presented to
67 the caller when it is first encountered in the pre-order traversal and that all data items are presented with its nesting level
68 and the nesting level of the next item.
69
70 The caller traverse maps and arrays in a special mode that often more convenient
71 that tracking by nesting level. When an array or map is expected or encountered
72 the EnterMap or EnteryArray can be called.
73
74 When entering a map or array like this, the cursor points to the first
75 item in the map or array. When exiting, it points to the item after
76 the map or array, regardless of whether the items in the map or array were
77 all traversed.
78
79 When in a map or array, the cursor functions as normal, but traversal
80 cannot go past the end of the map or array that was entered. If this
81 is attempted the QCBOR_ERR_NO_MORE_ITEMS error is returned. To
82 go past the end of the map or array ExitMap() or ExitArray() must
83 be called. It can be called any time regardless of the position
84 of the cursor.
85
86 When a map is entered, a special function allows fetching data items
87 by label. This call will traversal the whole map looking for the
88 labeled item. The whole map is traversed so as to detect duplicates.
89 This type of fetching items does not affect the normal traversal
90 cursor.
91
92
93
94
95
96
97
98
99
100
101When a data item is presented to the caller, the nesting level of the data
102 item is presented along with the nesting level of the item that would be
103 next consumed.
104
105
106
107
108
109
110
111
112
113 */
114
Laurence Lundblade6b249302020-04-30 12:38:12 -0700115inline static bool
116// TODO: test Map as array better?
Laurence Lundbladeee851742020-01-08 08:37:05 -0800117IsMapOrArray(uint8_t uDataType)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700118{
Laurence Lundblade6b249302020-04-30 12:38:12 -0700119 return uDataType == QCBOR_TYPE_MAP ||
120 uDataType == QCBOR_TYPE_ARRAY ||
121 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700122}
123
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700124inline static bool
125DecodeNesting_IsAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700126{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700127 if(pNesting->pCurrent == &(pNesting->pMapsAndArrays[0])) {
128 return true;
129 } else {
130 return false;
131 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700132}
133
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700134// Determine if at the end of a map or array, taking into
135// account map mode. If this returns true, it is OK
136// to get another item.
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700137inline static bool
138DecodeNesting_AtEnd(const QCBORDecodeNesting *pNesting)
139{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700140 if(DecodeNesting_IsAtTop(pNesting)){
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700141 // Always at end if at the top level of nesting
142 return true;
143 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700144
145 if(pNesting->pCurrent->uMapMode) {
146 if(pNesting->pCurrent->uCount == 0) {
147 // In map mode and consumed all items, so it is the end
148 return true;
149 } else {
150 // In map mode, all items not consumed, so it is NOT the end
151 return false;
152 }
153 } else {
154 // Not in map mode, and not at top level so it NOT the end.
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700155 return false;
156 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700157}
158
159
Laurence Lundbladeee851742020-01-08 08:37:05 -0800160inline static int
161DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700162{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700163 return pNesting->pCurrent->uCount == UINT16_MAX;
164}
165
Laurence Lundbladeee851742020-01-08 08:37:05 -0800166inline static uint8_t
167DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800168{
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800169 // Check in DecodeNesting_Descend and never having
Laurence Lundbladebb87be22020-04-09 19:15:32 -0700170 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800171 return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800172}
173
Laurence Lundbladeee851742020-01-08 08:37:05 -0800174inline static int
175DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700176{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700177 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700178 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700179 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800180
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700181 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
182}
183
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800184// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800185inline static QCBORError
186DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700187{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800188 // breaks must always occur when there is nesting
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700189 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800190 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700191 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800192
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800193 // breaks can only occur when the map/array is indefinite length
194 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
195 return QCBOR_ERR_BAD_BREAK;
196 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800197
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800198 // if all OK, the break reduces the level of nesting
199 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800200
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800201 return QCBOR_SUCCESS;
202}
203
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700204// Called on every single item except breaks including decode of a map/array
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700205/* Decrements the map/array counter if possible. If decrement
206 closed out a map or array, then level up in nesting and decrement
207 again, until, the top is reached or the end of a map mode is reached
208 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800209inline static void
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700210DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting, bool bExitingMapMode)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800211{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700212 while(!DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700213 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800214
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800215 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700216 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800217 pNesting->pCurrent->uCount--;
218 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700219
220 if(pNesting->pCurrent->uCount != 0) {
221 // Did not close out an array or map, so nothing further
222 break;
223 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700224
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700225 if(pNesting->pCurrent->uMapMode && !bExitingMapMode) {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700226 // In map mode the level-up must be done explicitly
227 break;
228 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700229
230 // Closed out an array or map so level up
231 pNesting->pCurrent--;
232
233 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700234 }
235}
236
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800237// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800238inline static QCBORError
239DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700240{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700241 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800242
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800243 if(pItem->val.uCount == 0) {
244 // Nothing to do for empty definite lenth arrays. They are just are
245 // effectively the same as an item that is not a map or array
246 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530247 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800248 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800249
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800250 // Error out if arrays is too long to handle
251 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700252 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
253 goto Done;
254 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800255
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800256 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700257 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
258 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
259 goto Done;
260 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800261
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800262 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700263 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800264
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800265 // Record a few details for this nesting level
266 pNesting->pCurrent->uMajorType = pItem->uDataType;
267 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700268 pNesting->pCurrent->uMapMode = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800269
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700270Done:
271 return nReturn;;
272}
273
Laurence Lundbladeee851742020-01-08 08:37:05 -0800274inline static void
275DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700276{
277 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
278}
279
280
281
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700282/*
283 This list of built-in tags. Only add tags here that are
284 clearly established and useful. Once a tag is added here
285 it can't be taken out as that would break backwards compatibility.
286 There are only 48 slots available forever.
287 */
288static const uint16_t spBuiltInTagMap[] = {
Laurence Lundblade59289e52019-12-30 13:44:37 -0800289 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
290 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
291 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
292 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
293 CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
294 CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700295 CBOR_TAG_COSE_ENCRYPTO,
296 CBOR_TAG_COSE_MAC0,
297 CBOR_TAG_COSE_SIGN1,
298 CBOR_TAG_ENC_AS_B64URL,
299 CBOR_TAG_ENC_AS_B64,
300 CBOR_TAG_ENC_AS_B16,
301 CBOR_TAG_CBOR,
302 CBOR_TAG_URI,
303 CBOR_TAG_B64URL,
304 CBOR_TAG_B64,
305 CBOR_TAG_REGEX,
306 CBOR_TAG_MIME,
307 CBOR_TAG_BIN_UUID,
308 CBOR_TAG_CWT,
309 CBOR_TAG_ENCRYPT,
310 CBOR_TAG_MAC,
311 CBOR_TAG_SIGN,
312 CBOR_TAG_GEO_COORD,
313 CBOR_TAG_CBOR_MAGIC
314};
315
316// This is used in a bit of cleverness in GetNext_TaggedItem() to
317// keep code size down and switch for the internal processing of
Laurence Lundblade59289e52019-12-30 13:44:37 -0800318// these types. This will break if the first six items in
319// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
320// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
321#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
322#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
323#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
324#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
325#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
326#define QCBOR_TAGFLAG_BIGFLOAT (0x01LL << CBOR_TAG_BIGFLOAT)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700327
Laurence Lundblade59289e52019-12-30 13:44:37 -0800328#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING |\
329 QCBOR_TAGFLAG_DATE_EPOCH |\
330 QCBOR_TAGFLAG_POS_BIGNUM |\
331 QCBOR_TAGFLAG_NEG_BIGNUM |\
332 QCBOR_TAGFLAG_DECIMAL_FRACTION |\
333 QCBOR_TAGFLAG_BIGFLOAT)
334
335#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
336 QCBOR_TAGFLAG_DATE_EPOCH |\
337 QCBOR_TAGFLAG_POS_BIGNUM |\
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700338 QCBOR_TAGFLAG_NEG_BIGNUM)
339
340#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
341#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
342#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
343
344static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
345{
346 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800347 /*
348 This is a cross-check to make sure the above array doesn't
349 accidentally get made too big. In normal conditions the above
350 test should optimize out as all the values are known at compile
351 time.
352 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700353 return -1;
354 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800355
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700356 if(uTag > UINT16_MAX) {
357 // This tag map works only on 16-bit tags
358 return -1;
359 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800360
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700361 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
362 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
363 return nTagBitIndex;
364 }
365 }
366 return -1; // Indicates no match
367}
368
369static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
370{
371 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
372 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
373 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
374 }
375 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800376
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700377 return -1; // Indicates no match
378}
379
380/*
381 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800382
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700383 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800384 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700385 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800386static QCBORError
387TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
388 uint64_t uTag,
389 uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700390{
391 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
392 if(nTagBitIndex >= 0) {
393 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
394 *puTagBitIndex = (uint8_t)nTagBitIndex;
395 return QCBOR_SUCCESS;
396 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800397
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700398 if(pCallerConfiguredTagMap) {
399 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
400 return QCBOR_ERR_TOO_MANY_TAGS;
401 }
402 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
403 if(nTagBitIndex >= 0) {
404 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
405
406 *puTagBitIndex = (uint8_t)nTagBitIndex;
407 return QCBOR_SUCCESS;
408 }
409 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800410
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700411 return QCBOR_ERR_BAD_OPT_TAG;
412}
413
414
415
Laurence Lundbladeee851742020-01-08 08:37:05 -0800416/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800417 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
418
419 The following four functions are pretty wrappers for invocation of
420 the string allocator supplied by the caller.
421
Laurence Lundbladeee851742020-01-08 08:37:05 -0800422 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800423
Laurence Lundbladeee851742020-01-08 08:37:05 -0800424static inline void
425StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800426{
427 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
428}
429
Laurence Lundbladeee851742020-01-08 08:37:05 -0800430// StringAllocator_Reallocate called with pMem NULL is
431// equal to StringAllocator_Allocate()
432static inline UsefulBuf
433StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
434 void *pMem,
435 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800436{
437 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
438}
439
Laurence Lundbladeee851742020-01-08 08:37:05 -0800440static inline UsefulBuf
441StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800442{
443 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
444}
445
Laurence Lundbladeee851742020-01-08 08:37:05 -0800446static inline void
447StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800448{
449 if(pMe->pfAllocator) {
450 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
451 }
452}
453
454
455
Laurence Lundbladeee851742020-01-08 08:37:05 -0800456/*===========================================================================
457 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700458
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800459 See qcbor/qcbor_decode.h for definition of the object
460 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800461 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700462/*
463 Public function, see header file
464 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800465void QCBORDecode_Init(QCBORDecodeContext *me,
466 UsefulBufC EncodedCBOR,
467 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700468{
469 memset(me, 0, sizeof(QCBORDecodeContext));
470 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800471 // Don't bother with error check on decode mode. If a bad value is
472 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700473 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700474 DecodeNesting_Init(&(me->nesting));
475}
476
477
478/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700479 Public function, see header file
480 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800481void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
482 QCBORStringAllocate pfAllocateFunction,
483 void *pAllocateContext,
484 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700485{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800486 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
487 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
488 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700489}
490
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800491
492/*
493 Public function, see header file
494 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800495void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
496 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700497{
498 me->pCallerConfiguredTagList = pTagList;
499}
500
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700501
502/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800503 This decodes the fundamental part of a CBOR data item, the type and
504 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800505
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700506 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800507
Laurence Lundbladeee851742020-01-08 08:37:05 -0800508 This does the network->host byte order conversion. The conversion
509 here also results in the conversion for floats in addition to that
510 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800511
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700512 This returns:
513 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800514
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800515 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800516 tags and floats and length for strings and arrays
517
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800518 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800519 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800520
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800521 The int type is preferred to uint8_t for some variables as this
522 avoids integer promotions, can reduce code size and makes
523 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700524 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800525inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
526 int *pnMajorType,
527 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800528 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700529{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700530 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800531
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700532 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800533 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800534
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700535 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800536 const int nTmpMajorType = nInitialByte >> 5;
537 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800538
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800539 // Where the number or argument accumulates
540 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800541
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800542 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800543 // Need to get 1,2,4 or 8 additional argument bytes Map
544 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800545 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800546
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800547 // Loop getting all the bytes in the argument
548 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800549 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800550 // This shift and add gives the endian conversion
551 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
552 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800553 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800554 // The reserved and thus-far unused additional info values
555 nReturn = QCBOR_ERR_UNSUPPORTED;
556 goto Done;
557 } else {
558 // Less than 24, additional info is argument or 31, an indefinite length
559 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800560 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700561 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800562
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700563 if(UsefulInputBuf_GetError(pUInBuf)) {
564 nReturn = QCBOR_ERR_HIT_END;
565 goto Done;
566 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800567
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700568 // All successful if we got here.
569 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800570 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800571 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800572 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800573
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700574Done:
575 return nReturn;
576}
577
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800578
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700579/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800580 CBOR doesn't explicitly specify two's compliment for integers but all
581 CPUs use it these days and the test vectors in the RFC are so. All
582 integers in the CBOR structure are positive and the major type
583 indicates positive or negative. CBOR can express positive integers
584 up to 2^x - 1 where x is the number of bits and negative integers
585 down to 2^x. Note that negative numbers can be one more away from
586 zero than positive. Stdint, as far as I can tell, uses two's
587 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800588
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700589 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800590 used carefully here, and in particular why it isn't used in the interface.
591 Also see
592 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
593
594 Int is used for values that need less than 16-bits and would be subject
595 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700596 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800597inline static QCBORError
598DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700599{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700600 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800601
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700602 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
603 if (uNumber <= INT64_MAX) {
604 pDecodedItem->val.int64 = (int64_t)uNumber;
605 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800606
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700607 } else {
608 pDecodedItem->val.uint64 = uNumber;
609 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800610
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700611 }
612 } else {
613 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800614 // CBOR's representation of negative numbers lines up with the
615 // two-compliment representation. A negative integer has one
616 // more in range than a positive integer. INT64_MIN is
617 // equal to (-INT64_MAX) - 1.
618 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700619 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800620
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700621 } else {
622 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000623 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700624 nReturn = QCBOR_ERR_INT_OVERFLOW;
625 }
626 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800627
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700628 return nReturn;
629}
630
631// Make sure #define value line up as DecodeSimple counts on this.
632#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
633#error QCBOR_TYPE_FALSE macro value wrong
634#endif
635
636#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
637#error QCBOR_TYPE_TRUE macro value wrong
638#endif
639
640#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
641#error QCBOR_TYPE_NULL macro value wrong
642#endif
643
644#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
645#error QCBOR_TYPE_UNDEF macro value wrong
646#endif
647
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700648#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
649#error QCBOR_TYPE_BREAK macro value wrong
650#endif
651
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700652#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
653#error QCBOR_TYPE_DOUBLE macro value wrong
654#endif
655
656#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
657#error QCBOR_TYPE_FLOAT macro value wrong
658#endif
659
660/*
661 Decode true, false, floats, break...
662 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800663inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800664DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700665{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700666 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800667
Laurence Lundbladeee851742020-01-08 08:37:05 -0800668 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800669 // above make sure uAdditionalInfo values line up with uDataType values.
670 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
671 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800672
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800673 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800674 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
675 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800676
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700677 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700678 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
679 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700680 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700681 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700682 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
683 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700684 break;
685 case DOUBLE_PREC_FLOAT:
686 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700687 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700688 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800689
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700690 case CBOR_SIMPLEV_FALSE: // 20
691 case CBOR_SIMPLEV_TRUE: // 21
692 case CBOR_SIMPLEV_NULL: // 22
693 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700694 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700695 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800696
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700697 case CBOR_SIMPLEV_ONEBYTE: // 24
698 if(uNumber <= CBOR_SIMPLE_BREAK) {
699 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700700 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701 goto Done;
702 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800703 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700704 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800705
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700706 default: // 0-19
707 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800708 /*
709 DecodeTypeAndNumber will make uNumber equal to
710 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
711 safe because the 2, 4 and 8 byte lengths of uNumber are in
712 the double/float cases above
713 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700714 pDecodedItem->val.uSimple = (uint8_t)uNumber;
715 break;
716 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800717
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700718Done:
719 return nReturn;
720}
721
722
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700723/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530724 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700725 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800726inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
727 int nMajorType,
728 uint64_t uStrLen,
729 UsefulInputBuf *pUInBuf,
730 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700731{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700732 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800733
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800734 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
735 // This check makes the casts to size_t below safe.
736
737 // 4 bytes less than the largest sizeof() so this can be tested by
738 // putting a SIZE_MAX length in the CBOR test input (no one will
739 // care the limit on strings is 4 bytes shorter).
740 if(uStrLen > SIZE_MAX-4) {
741 nReturn = QCBOR_ERR_STRING_TOO_LONG;
742 goto Done;
743 }
744
745 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530746 if(UsefulBuf_IsNULLC(Bytes)) {
747 // Failed to get the bytes for this string item
748 nReturn = QCBOR_ERR_HIT_END;
749 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700750 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530751
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800752 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530753 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800754 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530755 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700756 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530757 goto Done;
758 }
759 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800760 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530761 } else {
762 // Normal case with no string allocator
763 pDecodedItem->val.string = Bytes;
764 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800765 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800766 // Cast because ternary operator causes promotion to integer
767 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
768 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800769
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530770Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700771 return nReturn;
772}
773
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700774
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800775
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700776
777
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700778
779
Laurence Lundbladeee851742020-01-08 08:37:05 -0800780// Make sure the constants align as this is assumed by
781// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700782#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
783#error QCBOR_TYPE_ARRAY value not lined up with major type
784#endif
785#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
786#error QCBOR_TYPE_MAP value not lined up with major type
787#endif
788
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700789/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800790 This gets a single data item and decodes it including preceding
791 optional tagging. This does not deal with arrays and maps and nesting
792 except to decode the data item introducing them. Arrays and maps are
793 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800794
Laurence Lundbladeee851742020-01-08 08:37:05 -0800795 Errors detected here include: an array that is too long to decode,
796 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700797 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800798static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
799 QCBORItem *pDecodedItem,
800 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700801{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700802 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800803
Laurence Lundbladeee851742020-01-08 08:37:05 -0800804 /*
805 Get the major type and the number. Number could be length of more
806 bytes or the value depending on the major type nAdditionalInfo is
807 an encoding of the length of the uNumber and is needed to decode
808 floats and doubles
809 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800810 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700811 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800812 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800813
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700814 memset(pDecodedItem, 0, sizeof(QCBORItem));
815
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800816 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800817
Laurence Lundbladeee851742020-01-08 08:37:05 -0800818 // Error out here if we got into trouble on the type and number. The
819 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700820 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700821 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700822 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800823
Laurence Lundbladeee851742020-01-08 08:37:05 -0800824 // At this point the major type and the value are valid. We've got
825 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800826 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700827 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
828 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800829 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700830 nReturn = QCBOR_ERR_BAD_INT;
831 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800832 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700833 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700834 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800835
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700836 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
837 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800838 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
839 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
840 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
841 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530842 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700843 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800844 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700845 }
846 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800847
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700848 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
849 case CBOR_MAJOR_TYPE_MAP: // Major type 5
850 // Record the number of items in the array or map
851 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
852 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
853 goto Done;
854 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800855 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530856 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700857 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800858 // type conversion OK because of check above
859 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700860 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800861 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800862 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
863 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700864 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800865
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700866 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800867 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700868 nReturn = QCBOR_ERR_BAD_INT;
869 } else {
870 pDecodedItem->val.uTagV = uNumber;
871 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
872 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700873 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800874
Laurence Lundbladeee851742020-01-08 08:37:05 -0800875 case CBOR_MAJOR_TYPE_SIMPLE:
876 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800877 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700878 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800879
Laurence Lundbladeee851742020-01-08 08:37:05 -0800880 default:
881 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700882 nReturn = QCBOR_ERR_UNSUPPORTED;
883 break;
884 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800885
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700886Done:
887 return nReturn;
888}
889
890
891
892/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800893 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800894 individual chunk items together into one QCBORItem using the string
895 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800896
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530897 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700898 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800899static inline QCBORError
900GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700901{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700902 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700903
904 // Get pointer to string allocator. First use is to pass it to
905 // GetNext_Item() when option is set to allocate for *every* string.
906 // Second use here is to allocate space to coallese indefinite
907 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800908 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
909 &(me->StringAllocator) :
910 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800911
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700912 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800913 nReturn = GetNext_Item(&(me->InBuf),
914 pDecodedItem,
915 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700916 if(nReturn) {
917 goto Done;
918 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800919
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700920 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530921 // code in this function from here down can be eliminated. Run tests, except
922 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800923
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800924 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700925 const uint8_t uStringType = pDecodedItem->uDataType;
926 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700927 goto Done; // no need to do any work here on non-string types
928 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800929
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800930 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530931 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800932 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700933 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800934
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530935 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800936 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700937 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
938 goto Done;
939 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800940
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700941 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700942 UsefulBufC FullString = NULLUsefulBufC;
943
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700944 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700945 // Get item for next chunk
946 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700947 // NULL string allocator passed here. Do not need to allocate
948 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800949 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700950 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700951 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700952 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800953
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530954 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700955 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800956 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700957 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530958 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700959 break;
960 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800961
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700962 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530963 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700964 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800965 if(StringChunkItem.uDataType != uStringType ||
966 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700967 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700968 break;
969 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800970
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530971 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800972 // The first time throurgh FullString.ptr is NULL and this is
973 // equivalent to StringAllocator_Allocate()
974 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
975 UNCONST_POINTER(FullString.ptr),
976 FullString.len + StringChunkItem.val.string.len);
977
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700978 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530979 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700980 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981 break;
982 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800983
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700984 // Copy new string chunk at the end of string so far.
985 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700986 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800987
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800988 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
989 // Getting the item failed, clean up the allocated memory
990 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700991 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800992
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700993Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700994 return nReturn;
995}
996
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700997
998/*
Laurence Lundblade59289e52019-12-30 13:44:37 -0800999 Gets all optional tag data items preceding a data item that is not an
1000 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001001 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001002static QCBORError
1003GetNext_TaggedItem(QCBORDecodeContext *me,
1004 QCBORItem *pDecodedItem,
1005 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001006{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001007 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +07001008 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001009 uint64_t uTagBits = 0;
1010 if(pTags) {
1011 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001012 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001013
Laurence Lundblade59289e52019-12-30 13:44:37 -08001014 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001015 for(;;) {
1016 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001017 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001018 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001019 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001020
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001021 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1022 // Successful exit from loop; maybe got some tags, maybe not
1023 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001024 break;
1025 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001026
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001027 uint8_t uTagBitIndex;
1028 // Tag was mapped, tag was not mapped, error with tag list
1029 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001030
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001031 case QCBOR_SUCCESS:
1032 // Successfully mapped the tag
1033 uTagBits |= 0x01ULL << uTagBitIndex;
1034 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001035
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001036 case QCBOR_ERR_BAD_OPT_TAG:
1037 // Tag is not recognized. Do nothing
1038 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001039
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001040 default:
1041 // Error Condition
1042 goto Done;
1043 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001044
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001045 if(pTags) {
1046 // Caller wants all tags recorded in the provided buffer
1047 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1048 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
1049 goto Done;
1050 }
1051 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
1052 pTags->uNumUsed++;
1053 }
1054 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001055
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001056Done:
1057 return nReturn;
1058}
1059
1060
1061/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001062 This layer takes care of map entries. It combines the label and data
1063 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001064 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001065static inline QCBORError
1066GetNext_MapEntry(QCBORDecodeContext *me,
1067 QCBORItem *pDecodedItem,
1068 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001069{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001070 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +07001071 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001072 if(nReturn)
1073 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001074
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001075 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001076 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001077 goto Done;
1078 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001079
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001080 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1081 // In a map and caller wants maps decoded, not treated as arrays
1082
1083 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1084 // If in a map and the right decoding mode, get the label
1085
Laurence Lundbladeee851742020-01-08 08:37:05 -08001086 // Save label in pDecodedItem and get the next which will
1087 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001088 QCBORItem LabelItem = *pDecodedItem;
1089 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1090 if(nReturn)
1091 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001092
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301093 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001094
1095 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1096 // strings are always good labels
1097 pDecodedItem->label.string = LabelItem.val.string;
1098 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1099 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001100 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001101 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1102 goto Done;
1103 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1104 pDecodedItem->label.int64 = LabelItem.val.int64;
1105 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1106 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1107 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1108 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1109 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1110 pDecodedItem->label.string = LabelItem.val.string;
1111 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1112 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1113 } else {
1114 // label is not an int or a string. It is an arrray
1115 // or a float or such and this implementation doesn't handle that.
1116 // Also, tags on labels are ignored.
1117 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1118 goto Done;
1119 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001120 }
1121 } else {
1122 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001123 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1124 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1125 goto Done;
1126 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001127 // Decoding a map as an array
1128 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001129 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1130 // Cast is needed because of integer promotion
1131 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001132 }
1133 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001134
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001135Done:
1136 return nReturn;
1137}
1138
1139
1140/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001141 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001142 TODO: correct this comment
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001143 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001144QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
1145 QCBORItem *pDecodedItem,
1146 QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001147{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001148 // Stack ptr/int: 2, QCBORItem : 64
1149
Laurence Lundblade30816f22018-11-10 13:40:22 +07001150 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001151
Laurence Lundblade1341c592020-04-11 14:19:05 -07001152 // Check if there are an TODO: incomplete comment
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001153 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001154 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1155 goto Done;
1156 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001157
1158 // This is to handle map and array mode
1159 if(UsefulInputBuf_Tell(&(me->InBuf)) != 0 && DecodeNesting_AtEnd(&(me->nesting))) {
1160 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1161 goto Done;
1162 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001163
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001164 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001165 if(nReturn) {
1166 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001167 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301168
1169 // Break ending arrays/maps are always processed at the end of this function.
1170 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301171 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301172 nReturn = QCBOR_ERR_BAD_BREAK;
1173 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301174 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001175
Laurence Lundblade6de37062018-10-15 12:22:42 +05301176 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301177 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301178 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001179
Laurence Lundblade6de37062018-10-15 12:22:42 +05301180 // Process the item just received for descent or decrement, and
1181 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001182 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001183 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001184 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001185 // Maps and arrays do count in as items in the map/array that encloses
1186 // them so a decrement needs to be done for them too, but that is done
1187 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001188 // are opened with the exception of an empty map or array.
1189 if(pDecodedItem->val.uCount == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001190 DecodeNesting_DecrementCount(&(me->nesting), false);
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001191 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001192 } else {
1193 // Decrement the count of items in the enclosing map/array
1194 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301195 // triggers a decrement in the map/array above that and
1196 // an ascend in nesting level.
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001197 DecodeNesting_DecrementCount(&(me->nesting), false);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001198 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301199 if(nReturn) {
1200 goto Done;
1201 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001202
Laurence Lundblade6de37062018-10-15 12:22:42 +05301203 // For indefinite length maps/arrays, looking at any and
1204 // all breaks that might terminate them. The equivalent
1205 // for definite length maps/arrays happens in
1206 // DecodeNesting_DecrementCount().
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001207 if(!DecodeNesting_IsAtTop(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301208 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1209 // Peek forward one item to see if it is a break.
1210 QCBORItem Peek;
1211 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1212 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1213 if(nReturn) {
1214 goto Done;
1215 }
1216 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1217 // It is not a break, rewind so it can be processed normally.
1218 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1219 break;
1220 }
1221 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301222 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301223 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1224 if(nReturn) {
1225 // break occured outside of an indefinite length array/map
1226 goto Done;
1227 }
1228 }
1229 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001230
Laurence Lundblade6de37062018-10-15 12:22:42 +05301231 // Tell the caller what level is next. This tells them what maps/arrays
1232 // were closed out and makes it possible for them to reconstruct
1233 // the tree with just the information returned by GetNext
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001234 if(me->nesting.pCurrent->uMapMode && me->nesting.pCurrent->uCount == 0) {
1235 // At end of a map / array in map mode, so next nest is 0 to
1236 // indicate this end.
1237 pDecodedItem->uNextNestLevel = 0;
1238 } else {
1239 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
1240 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001241
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001242Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001243 if(nReturn != QCBOR_SUCCESS) {
1244 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1245 memset(pDecodedItem, 0, sizeof(QCBORItem));
1246 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001247 return nReturn;
1248}
1249
1250
Laurence Lundblade59289e52019-12-30 13:44:37 -08001251/*
1252 Mostly just assign the right data type for the date string.
1253 */
1254inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1255{
1256 // Stack Use: UsefulBuf 1 16
1257 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1258 return QCBOR_ERR_BAD_OPT_TAG;
1259 }
1260
1261 const UsefulBufC Temp = pDecodedItem->val.string;
1262 pDecodedItem->val.dateString = Temp;
1263 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1264 return QCBOR_SUCCESS;
1265}
1266
1267
1268/*
1269 Mostly just assign the right data type for the bignum.
1270 */
1271inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1272{
1273 // Stack Use: UsefulBuf 1 -- 16
1274 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1275 return QCBOR_ERR_BAD_OPT_TAG;
1276 }
1277 const UsefulBufC Temp = pDecodedItem->val.string;
1278 pDecodedItem->val.bigNum = Temp;
Laurence Lundbladeee851742020-01-08 08:37:05 -08001279 const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001280 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1281 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001282 return QCBOR_SUCCESS;
1283}
1284
1285
1286/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001287 The epoch formatted date. Turns lots of different forms of encoding
1288 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001289 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001290static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001291{
1292 // Stack usage: 1
1293 QCBORError nReturn = QCBOR_SUCCESS;
1294
1295 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1296
1297 switch (pDecodedItem->uDataType) {
1298
1299 case QCBOR_TYPE_INT64:
1300 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1301 break;
1302
1303 case QCBOR_TYPE_UINT64:
1304 if(pDecodedItem->val.uint64 > INT64_MAX) {
1305 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1306 goto Done;
1307 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001308 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001309 break;
1310
1311 case QCBOR_TYPE_DOUBLE:
1312 {
1313 // This comparison needs to be done as a float before
1314 // conversion to an int64_t to be able to detect doubles
1315 // that are too large to fit into an int64_t. A double
1316 // has 52 bits of preceision. An int64_t has 63. Casting
1317 // INT64_MAX to a double actually causes a round up which
1318 // is bad and wrong for the comparison because it will
1319 // allow conversion of doubles that can't fit into a
1320 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1321 // the cutoff point as if that rounds up in conversion to
1322 // double it will still be less than INT64_MAX. 0x7ff is
1323 // picked because it has 11 bits set.
1324 //
1325 // INT64_MAX seconds is on the order of 10 billion years,
1326 // and the earth is less than 5 billion years old, so for
1327 // most uses this conversion error won't occur even though
1328 // doubles can go much larger.
1329 //
1330 // Without the 0x7ff there is a ~30 minute range of time
1331 // values 10 billion years in the past and in the future
1332 // where this this code would go wrong.
1333 const double d = pDecodedItem->val.dfnum;
1334 if(d > (double)(INT64_MAX - 0x7ff)) {
1335 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1336 goto Done;
1337 }
1338 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1339 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1340 }
1341 break;
1342
1343 default:
1344 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1345 goto Done;
1346 }
1347 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1348
1349Done:
1350 return nReturn;
1351}
1352
1353
1354#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1355/*
1356 Decode decimal fractions and big floats.
1357
1358 When called pDecodedItem must be the array that is tagged as a big
1359 float or decimal fraction, the array that has the two members, the
1360 exponent and mantissa.
1361
1362 This will fetch and decode the exponent and mantissa and put the
1363 result back into pDecodedItem.
1364 */
1365inline static QCBORError
1366QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1367{
1368 QCBORError nReturn;
1369
1370 // --- Make sure it is an array; track nesting level of members ---
1371 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1372 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1373 goto Done;
1374 }
1375
1376 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001377 // definite length arrays, but not for indefnite. Instead remember
1378 // the nesting level the two integers must be at, which is one
1379 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001380 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1381
1382 // --- Is it a decimal fraction or a bigfloat? ---
1383 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1384 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1385
1386 // --- Get the exponent ---
1387 QCBORItem exponentItem;
1388 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
1389 if(nReturn != QCBOR_SUCCESS) {
1390 goto Done;
1391 }
1392 if(exponentItem.uNestingLevel != nNestLevel) {
1393 // Array is empty or a map/array encountered when expecting an int
1394 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1395 goto Done;
1396 }
1397 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1398 // Data arriving as an unsigned int < INT64_MAX has been converted
1399 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1400 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1401 // will be too large for this to handle and thus an error that will
1402 // get handled in the next else.
1403 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1404 } else {
1405 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1406 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1407 goto Done;
1408 }
1409
1410 // --- Get the mantissa ---
1411 QCBORItem mantissaItem;
1412 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1413 if(nReturn != QCBOR_SUCCESS) {
1414 goto Done;
1415 }
1416 if(mantissaItem.uNestingLevel != nNestLevel) {
1417 // Mantissa missing or map/array encountered when expecting number
1418 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1419 goto Done;
1420 }
1421 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1422 // Data arriving as an unsigned int < INT64_MAX has been converted
1423 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1424 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1425 // will be too large for this to handle and thus an error that
1426 // will get handled in an else below.
1427 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1428 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1429 // Got a good big num mantissa
1430 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1431 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001432 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1433 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1434 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001435 } else {
1436 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1437 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1438 goto Done;
1439 }
1440
1441 // --- Check that array only has the two numbers ---
1442 if(mantissaItem.uNextNestLevel == nNestLevel) {
1443 // Extra items in the decimal fraction / big num
1444 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1445 goto Done;
1446 }
1447
1448Done:
1449
1450 return nReturn;
1451}
1452#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1453
1454
1455/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001456 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001457 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001458QCBORError
1459QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1460 QCBORItem *pDecodedItem,
1461 QCBORTagListOut *pTags)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001462{
1463 QCBORError nReturn;
1464
1465 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
1466 if(nReturn != QCBOR_SUCCESS) {
1467 goto Done;
1468 }
1469
1470#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1471#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
1472#else
1473#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
1474#endif
1475
1476 // Only pay attention to tags this code knows how to decode.
1477 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
1478 case 0:
1479 // No tags at all or none we know about. Nothing to do.
1480 // This is the pass-through path of this function
1481 // that will mostly be taken when decoding any item.
1482 break;
1483
1484 case QCBOR_TAGFLAG_DATE_STRING:
1485 nReturn = DecodeDateString(pDecodedItem);
1486 break;
1487
1488 case QCBOR_TAGFLAG_DATE_EPOCH:
1489 nReturn = DecodeDateEpoch(pDecodedItem);
1490 break;
1491
1492 case QCBOR_TAGFLAG_POS_BIGNUM:
1493 case QCBOR_TAGFLAG_NEG_BIGNUM:
1494 nReturn = DecodeBigNum(pDecodedItem);
1495 break;
1496
1497#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1498 case QCBOR_TAGFLAG_DECIMAL_FRACTION:
1499 case QCBOR_TAGFLAG_BIGFLOAT:
1500 // For aggregate tagged types, what goes into pTags is only collected
1501 // from the surrounding data item, not the contents, so pTags is not
1502 // passed on here.
1503
1504 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1505 break;
1506#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1507
1508 default:
1509 // Encountering some mixed-up CBOR like something that
1510 // is tagged as both a string and integer date.
1511 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1512 }
1513
1514Done:
1515 if(nReturn != QCBOR_SUCCESS) {
1516 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1517 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1518 }
1519 return nReturn;
1520}
1521
1522
1523/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001524 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001525 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001526QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001527{
1528 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1529}
1530
1531
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001532/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301533 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301534 next one down. If a layer has no work to do for a particular item
1535 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001536
Laurence Lundblade59289e52019-12-30 13:44:37 -08001537 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1538 tagged data items, turning them into the local C representation.
1539 For the most simple it is just associating a QCBOR_TYPE with the data. For
1540 the complex ones that an aggregate of data items, there is some further
1541 decoding and a little bit of recursion.
1542
1543 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301544 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301545 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001546 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001547
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301548 - GetNext_MapEntry -- This handles the combining of two
1549 items, the label and the data, that make up a map entry.
1550 It only does work on maps. It combines the label and data
1551 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001552
Laurence Lundblade59289e52019-12-30 13:44:37 -08001553 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1554 tags into bit flags associated with the data item. No actual decoding
1555 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001556
Laurence Lundblade59289e52019-12-30 13:44:37 -08001557 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301558 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301559 string allocater to create contiguous space for the item. It
1560 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001561
Laurence Lundblade59289e52019-12-30 13:44:37 -08001562 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1563 atomic data item has a "major type", an integer "argument" and optionally
1564 some content. For text and byte strings, the content is the bytes
1565 that make up the string. These are the smallest data items that are
1566 considered to be well-formed. The content may also be other data items in
1567 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001568
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001569 Roughly this takes 300 bytes of stack for vars. Need to
1570 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001571
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301572 */
1573
1574
1575/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001576 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001577 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001578int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1579 const QCBORItem *pItem,
1580 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001581{
1582 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001583
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001584 uint8_t uTagBitIndex;
1585 // Do not care about errors in pCallerConfiguredTagMap here. They are
1586 // caught during GetNext() before this is called.
1587 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1588 return 0;
1589 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001590
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001591 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1592 return (uTagBit & pItem->uTagBits) != 0;
1593}
1594
1595
1596/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001597 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001598 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001599QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001600{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001601 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001602
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001603 // Error out if all the maps/arrays are not closed out
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001604 if(!DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001605 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1606 goto Done;
1607 }
1608
1609 // Error out if not all the bytes are consumed
1610 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1611 nReturn = QCBOR_ERR_EXTRA_BYTES;
1612 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001613
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001614Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301615 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001616 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001617 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001618
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001619 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001620}
1621
1622
1623
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001624/*
1625
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001626Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001627
Laurence Lundbladeee851742020-01-08 08:37:05 -08001628 - Hit end of input before it was expected while decoding type and
1629 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001630
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001631 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001632
Laurence Lundbladeee851742020-01-08 08:37:05 -08001633 - Hit end of input while decoding a text or byte string
1634 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001635
Laurence Lundbladeee851742020-01-08 08:37:05 -08001636 - Encountered conflicting tags -- e.g., an item is tagged both a date
1637 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001638
Laurence Lundbladeee851742020-01-08 08:37:05 -08001639 - Encontered an array or mapp that has too many items
1640 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001641
Laurence Lundbladeee851742020-01-08 08:37:05 -08001642 - Encountered array/map nesting that is too deep
1643 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001644
Laurence Lundbladeee851742020-01-08 08:37:05 -08001645 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1646 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001647
Laurence Lundbladeee851742020-01-08 08:37:05 -08001648 - The type of a map label is not a string or int
1649 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001650
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001651 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001652
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001653 */
1654
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001655
1656
Laurence Lundbladef6531662018-12-04 10:42:22 +09001657
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001658/* ===========================================================================
1659 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001660
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001661 This implements a simple sting allocator for indefinite length
1662 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1663 implements the function type QCBORStringAllocate and allows easy
1664 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001665
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001666 This particular allocator is built-in for convenience. The caller
1667 can implement their own. All of this following code will get
1668 dead-stripped if QCBORDecode_SetMemPool() is not called.
1669
1670 This is a very primitive memory allocator. It does not track
1671 individual allocations, only a high-water mark. A free or
1672 reallocation must be of the last chunk allocated.
1673
1674 The size of the pool and offset to free memory are packed into the
1675 first 8 bytes of the memory pool so we don't have to keep them in
1676 the decode context. Since the address of the pool may not be
1677 aligned, they have to be packed and unpacked as if they were
1678 serialized data of the wire or such.
1679
1680 The sizes packed in are uint32_t to be the same on all CPU types
1681 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001682 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001683
1684
Laurence Lundbladeee851742020-01-08 08:37:05 -08001685static inline int
1686MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001687{
1688 // Use of UsefulInputBuf is overkill, but it is convenient.
1689 UsefulInputBuf UIB;
1690
Laurence Lundbladeee851742020-01-08 08:37:05 -08001691 // Just assume the size here. It was checked during SetUp so
1692 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001693 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1694 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1695 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1696 return UsefulInputBuf_GetError(&UIB);
1697}
1698
1699
Laurence Lundbladeee851742020-01-08 08:37:05 -08001700static inline int
1701MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001702{
1703 // Use of UsefulOutBuf is overkill, but convenient. The
1704 // length check performed here is useful.
1705 UsefulOutBuf UOB;
1706
1707 UsefulOutBuf_Init(&UOB, Pool);
1708 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1709 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1710 return UsefulOutBuf_GetError(&UOB);
1711}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001712
1713
1714/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001715 Internal function for an allocation, reallocation free and destuct.
1716
1717 Having only one function rather than one each per mode saves space in
1718 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001719
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001720 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1721 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001722static UsefulBuf
1723MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001724{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001725 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001726
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001727 uint32_t uPoolSize;
1728 uint32_t uFreeOffset;
1729
1730 if(uNewSize > UINT32_MAX) {
1731 // This allocator is only good up to 4GB. This check should
1732 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1733 goto Done;
1734 }
1735 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1736
1737 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1738 goto Done;
1739 }
1740
1741 if(uNewSize) {
1742 if(pMem) {
1743 // REALLOCATION MODE
1744 // Calculate pointer to the end of the memory pool. It is
1745 // assumed that pPool + uPoolSize won't wrap around by
1746 // assuming the caller won't pass a pool buffer in that is
1747 // not in legitimate memory space.
1748 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1749
1750 // Check that the pointer for reallocation is in the range of the
1751 // pool. This also makes sure that pointer math further down
1752 // doesn't wrap under or over.
1753 if(pMem >= pPool && pMem < pPoolEnd) {
1754 // Offset to start of chunk for reallocation. This won't
1755 // wrap under because of check that pMem >= pPool. Cast
1756 // is safe because the pool is always less than UINT32_MAX
1757 // because of check in QCBORDecode_SetMemPool().
1758 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1759
1760 // Check to see if the allocation will fit. uPoolSize -
1761 // uMemOffset will not wrap under because of check that
1762 // pMem is in the range of the uPoolSize by check above.
1763 if(uNewSize <= uPoolSize - uMemOffset) {
1764 ReturnValue.ptr = pMem;
1765 ReturnValue.len = uNewSize;
1766
1767 // Addition won't wrap around over because uNewSize was
1768 // checked to be sure it is less than the pool size.
1769 uFreeOffset = uMemOffset + uNewSize32;
1770 }
1771 }
1772 } else {
1773 // ALLOCATION MODE
1774 // uPoolSize - uFreeOffset will not underflow because this
1775 // pool implementation makes sure uFreeOffset is always
1776 // smaller than uPoolSize through this check here and
1777 // reallocation case.
1778 if(uNewSize <= uPoolSize - uFreeOffset) {
1779 ReturnValue.len = uNewSize;
1780 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001781 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001782 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001783 }
1784 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001785 if(pMem) {
1786 // FREE MODE
1787 // Cast is safe because of limit on pool size in
1788 // QCBORDecode_SetMemPool()
1789 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1790 } else {
1791 // DESTRUCT MODE
1792 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001793 }
1794 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001795
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001796 UsefulBuf Pool = {pPool, uPoolSize};
1797 MemPool_Pack(Pool, uFreeOffset);
1798
1799Done:
1800 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001801}
1802
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001803
Laurence Lundbladef6531662018-12-04 10:42:22 +09001804/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001805 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09001806 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001807QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1808 UsefulBuf Pool,
1809 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001810{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001811 // The pool size and free mem offset are packed into the beginning
1812 // of the pool memory. This compile time check make sure the
1813 // constant in the header is correct. This check should optimize
1814 // down to nothing.
1815 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001816 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001817 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001818
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001819 // The pool size and free offset packed in to the beginning of pool
1820 // memory are only 32-bits. This check will optimize out on 32-bit
1821 // machines.
1822 if(Pool.len > UINT32_MAX) {
1823 return QCBOR_ERR_BUFFER_TOO_LARGE;
1824 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001825
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001826 // This checks that the pool buffer given is big enough.
1827 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1828 return QCBOR_ERR_BUFFER_TOO_SMALL;
1829 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001830
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001831 pMe->StringAllocator.pfAllocator = MemPool_Function;
1832 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1833 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001834
Laurence Lundblade30816f22018-11-10 13:40:22 +07001835 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001836}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001837
Laurence Lundblade1341c592020-04-11 14:19:05 -07001838#include <stdio.h>
1839void printdecode(QCBORDecodeContext *pMe, const char *szName)
1840{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001841 printf("---%s--%d--%d--\nLevel Count Type Offset SaveCount MapMode\n",
1842 szName,
1843 (uint32_t)pMe->InBuf.cursor,
1844 (uint32_t)pMe->InBuf.UB.len);
1845/* for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
1846 if(&(pMe->nesting.pMapsAndArrays[i]) > pMe->nesting.pCurrent) {
1847 break;
1848 }
1849 printf(" %2d %5d %s %6u %2d %d\n",
Laurence Lundblade1341c592020-04-11 14:19:05 -07001850 i,
1851 pMe->nesting.pMapsAndArrays[i].uCount,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001852 pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_MAP ? " map" :
1853 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_ARRAY ? "array" :
1854 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_NONE ? " none" : "?????")),
Laurence Lundblade1341c592020-04-11 14:19:05 -07001855 pMe->nesting.pMapsAndArrays[i].uOffset,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001856 pMe->nesting.pMapsAndArrays[i].uSaveCount,
1857 pMe->nesting.pMapsAndArrays[i].uMapMode
Laurence Lundblade1341c592020-04-11 14:19:05 -07001858 );
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001859
Laurence Lundblade1341c592020-04-11 14:19:05 -07001860 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001861 printf("\n"); */
Laurence Lundblade1341c592020-04-11 14:19:05 -07001862}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001863
1864
1865/*
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001866 *
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001867 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001868static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001869ConsumeItem(QCBORDecodeContext *pMe,
1870 const QCBORItem *pItemToConsume,
1871 uint_fast8_t *puNextNestLevel)
1872{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001873 QCBORError nReturn;
1874 QCBORItem Item;
1875
1876 printdecode(pMe, "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001877
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001878 if(IsMapOrArray(pItemToConsume->uDataType)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001879 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001880
Laurence Lundblade1341c592020-04-11 14:19:05 -07001881 /* This works for definite and indefinite length
1882 * maps and arrays by using the nesting level
1883 */
1884 do {
1885 nReturn = QCBORDecode_GetNext(pMe, &Item);
1886 if(nReturn != QCBOR_SUCCESS) {
1887 goto Done;
1888 }
1889 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001890
Laurence Lundblade1341c592020-04-11 14:19:05 -07001891 if(puNextNestLevel != NULL) {
1892 *puNextNestLevel = Item.uNextNestLevel;
1893 }
1894 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001895
Laurence Lundblade1341c592020-04-11 14:19:05 -07001896 } else {
1897 /* item_to_consume is not a map or array */
1898 if(puNextNestLevel != NULL) {
1899 /* Just pass the nesting level through */
1900 *puNextNestLevel = pItemToConsume->uNextNestLevel;
1901 }
1902 nReturn = QCBOR_SUCCESS;
1903 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001904
1905Done:
1906 return nReturn;
1907}
1908
1909
Laurence Lundblade1341c592020-04-11 14:19:05 -07001910/* Return true if the labels in Item1 and Item2 are the same.
1911 Works only for integer and string labels. Returns false
1912 for any other type. */
1913static inline bool
1914MatchLabel(QCBORItem Item1, QCBORItem Item2)
1915{
1916 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
1917 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
1918 return true;
1919 }
1920 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
1921 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
1922 return true;
1923 }
1924 }
1925 /* Other label types are never matched */
1926 return false;
1927}
1928
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001929/*
1930 * Public function. qcbor_util.h
1931 */
1932QCBORError
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001933GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemArray, size_t *puOffset, size_t *puEndOffset)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001934{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001935 QCBORItem *pIterator;
1936 QCBORError nReturn;
1937
1938
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001939
Laurence Lundblade1341c592020-04-11 14:19:05 -07001940 printdecode(pMe, "GetItemsInMapStart");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001941
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001942
Laurence Lundblade1341c592020-04-11 14:19:05 -07001943 // TODO: check we are in map mode
1944
1945 /* Clear structure holding the items found */
1946 for(pIterator = pItemArray; pIterator->uLabelType != 0; pIterator++) {
1947 pIterator->uDataType = QCBOR_TYPE_NONE;
1948 }
1949
1950 // Save the cursor and such used for pre-order traversal
1951/* const size_t uSave = UsefulInputBuf_Tell(&(pMe->InBuf));
1952 const uint16_t uSaveCount = pMe->nesting.pCurrent->uCount;
1953 struct nesting_decode_level *pSaveCurrent = pMe->nesting.pCurrent;
1954*/
1955 QCBORDecodeNesting N = pMe->nesting;
1956
1957 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
1958 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
1959 }
1960
1961 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
1962
1963 /* Loop over all the items in the map. They could be
1964 * deeply nested and this should handle both definite
1965 * and indefinite length maps and arrays, so this
1966 * adds some complexity. */
1967 const uint8_t uMapNestLevel = DecodeNesting_GetLevel(&(pMe->nesting));
1968
1969 while(1) {
1970 QCBORItem Item;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001971
Laurence Lundblade1341c592020-04-11 14:19:05 -07001972 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001973
Laurence Lundblade1341c592020-04-11 14:19:05 -07001974 printdecode(pMe, "GetItemsInMapMid1");
1975
1976 if((nReturn = QCBORDecode_GetNext(pMe, &Item)) != QCBOR_SUCCESS) {
1977 /* Got non-well-formed CBOR */
1978 goto Done;
1979 }
1980
1981 printdecode(pMe, "GetItemsInMapMid2");
1982
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001983
Laurence Lundblade1341c592020-04-11 14:19:05 -07001984 // Loop over all the items to check this item against
1985 for(pIterator = pItemArray; pIterator->uLabelType != 0; pIterator++) {
1986 if(MatchLabel(Item, *pIterator)) {
1987 // A label match has been found
1988 if(pIterator->uDataType != QCBOR_TYPE_NONE) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001989 nReturn = QCBOR_ERR_DUPLICATE_LABEL;
1990 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07001991 }
1992
1993 /* Successful match. Return the item. */
1994 *pIterator = Item;
1995 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001996 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07001997 }
1998 }
1999 }
2000
2001 /* Still have to consume the item that did or didn't match.
2002 The item could be a deeply nested array or map. */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002003
2004 /* Only looking at top-level data items, so just consume any
2005 * map or array encountered.*/
Laurence Lundblade1341c592020-04-11 14:19:05 -07002006 uint_fast8_t uNextNestLevel;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002007
Laurence Lundblade1341c592020-04-11 14:19:05 -07002008 nReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2009 if(nReturn) {
2010 goto Done;
2011 }
2012 if(uNextNestLevel < uMapNestLevel) {
2013 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002014 /* Got all the items in the map. This is the non-error exit
2015 * from the loop. */
2016 // Cast OK because encoded CBOR is limited to UINT32_MAX
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002017 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
2018 pMe->uMapEndOffset = (uint32_t)uEndOffset;
2019 // TODO: is zero *puOffset OK?
2020 if(puEndOffset) {
2021 *puEndOffset = uEndOffset;
2022 }
2023 // TODO: record the offset here for exit to save CPU time
Laurence Lundblade1341c592020-04-11 14:19:05 -07002024 break;
2025 }
2026 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002027
2028Done:
Laurence Lundblade1341c592020-04-11 14:19:05 -07002029 printdecode(pMe, "GetItemsInMapBeforeDone");
2030
2031
2032 // Restore cursor for pre-order traversal
2033 /*
2034 pMe->nesting.pCurrent = pSaveCurrent;
2035 pMe->nesting.pCurrent->uCount = uSaveCount;
2036 UsefulInputBuf_Seek(&(pMe->InBuf), uSave);
2037 */
2038 pMe->nesting = N;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002039
Laurence Lundblade1341c592020-04-11 14:19:05 -07002040 printdecode(pMe, "GetItemsInMapEnd");
2041
2042 return nReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002043}
2044
2045void QCBORDecode_ExitMap(QCBORDecodeContext *pMe)
2046{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002047 size_t uEndOffset;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002048
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002049/*
Laurence Lundblade1341c592020-04-11 14:19:05 -07002050 if(pMe->uMapEndOffset) {
2051 uEndOffset = pMe->uMapEndOffset;
2052 // It is only valid once.
2053 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002054 } else { */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002055 QCBORItem Dummy;
2056
2057 Dummy.uLabelType = QCBOR_TYPE_NONE;
2058
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002059 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002060
2061 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002062// }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002063
2064 printdecode(pMe, "start exit");
2065 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2066
2067 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
2068 pMe->nesting.pCurrent->uCount = 1;
2069 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002070 pMe->nesting.pCurrent->uMapMode = 0;
2071
2072 DecodeNesting_DecrementCount(&(pMe->nesting), true);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002073 printdecode(pMe, "end exit");
2074
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002075}
2076
2077
2078QCBORError QCBORDecode_GetItemInMap(QCBORDecodeContext *pMe,
Laurence Lundblade1341c592020-04-11 14:19:05 -07002079 int64_t nLabel,
2080 uint8_t uQcborType,
2081 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002082{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002083 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002084
Laurence Lundblade1341c592020-04-11 14:19:05 -07002085 One[0].uLabelType = QCBOR_TYPE_INT64;
2086 One[0].label.int64 = nLabel;
2087 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2088
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002089 QCBORError nReturn = GetItemsInMap(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002090 if(nReturn) {
2091 return nReturn;
2092 }
2093
2094 if(One[0].uDataType == QCBOR_TYPE_NONE) {
2095 return QCBOR_ERR_NOT_FOUND;
2096 }
2097
2098 if(One[0].uDataType != uQcborType) {
2099 return QCBOR_ERR_UNEXPECTED_TYPE;
2100 }
2101
2102 *pItem = One[0];
2103
2104 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002105}
2106
2107
2108QCBORError QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade1341c592020-04-11 14:19:05 -07002109 const char *szLabel,
2110 uint8_t uQcborType,
2111 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002112{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002113 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002114
Laurence Lundblade1341c592020-04-11 14:19:05 -07002115 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2116 One[0].label.string = UsefulBuf_FromSZ(szLabel);
2117 One[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
2118
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002119 QCBORError nReturn = GetItemsInMap(pMe, One, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002120 if(nReturn) {
2121 return nReturn;
2122 }
2123
2124 if(One[0].uDataType == QCBOR_TYPE_NONE) {
2125 return QCBOR_ERR_NOT_FOUND;
2126 }
2127
2128 if(One[0].uDataType != uQcborType) {
2129 return QCBOR_ERR_UNEXPECTED_TYPE;
2130 }
2131
2132 *pItem = One[0];
2133
2134 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002135}
2136
2137
2138void QCBORDecode_GetBstrInMap(QCBORDecodeContext *pMe, int64_t nLabel, UsefulBufC *pBstr)
2139{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002140 // TODO: error handling
2141 QCBORItem Item;
2142 QCBORDecode_GetItemInMap(pMe, nLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2143 *pBstr = Item.val.string;
2144}
2145
2146void QCBORDecode_GetBstrInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2147{
2148 // TODO: error handling
2149 QCBORItem Item;
2150 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_BYTE_STRING, &Item);
2151 *pBstr = Item.val.string;
2152}
2153
2154void QCBORDecode_GetTextInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr)
2155{
2156 // TODO: error handling
2157 QCBORItem Item;
2158 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_TEXT_STRING, &Item);
2159 *pBstr = Item.val.string;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002160}
2161
2162
2163QCBORError QCBORDecode_EnterMapInMap(QCBORDecodeContext *pMe, int64_t nLabel)
2164{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002165 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002166
Laurence Lundblade1341c592020-04-11 14:19:05 -07002167 One[0].uLabelType = QCBOR_TYPE_INT64;
2168 One[0].label.int64 = nLabel;
2169 One[1].uLabelType = QCBOR_TYPE_NONE;
2170
2171 size_t uOffset;
2172
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002173 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002174
2175 if(nReturn) {
2176 return nReturn;
2177 }
2178
2179 if(One[0].uDataType != QCBOR_TYPE_MAP) {
2180 return QCBOR_ERR_UNEXPECTED_TYPE;
2181 }
2182
2183 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2184
2185 DecodeNesting_Descend(&(pMe->nesting), &One[1]);
2186
2187 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2188 pMe->nesting.pCurrent->uMapMode = 1;
2189
2190 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002191}
2192
2193
2194QCBORError QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2195{
2196 QCBORItem One[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002197
Laurence Lundblade1341c592020-04-11 14:19:05 -07002198 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2199 One[0].label.string = UsefulBuf_FromSZ(szLabel);
2200 One[1].uLabelType = QCBOR_TYPE_NONE;
2201
2202 size_t uOffset;
2203
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002204 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002205
2206 if(nReturn) {
2207 return nReturn;
2208 }
2209
2210 if(One[0].uDataType != QCBOR_TYPE_MAP) {
2211 return QCBOR_ERR_UNEXPECTED_TYPE;
2212 }
2213
2214 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2215
2216 QCBORItem MapToEnter;
2217 QCBORDecode_GetNext(pMe, &MapToEnter);
2218
2219
2220 // DecodeNesting_Descend(&(pMe->nesting), &One[1]);
2221
2222 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2223 pMe->nesting.pCurrent->uMapMode = 1;
2224 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
2225
2226 printdecode(pMe, "Entered Map in Map");
2227
2228 return 0;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002229}
2230
2231
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002232QCBORError QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t uLabel)
2233{
2234 (void)pMe; (void)uLabel;
2235 return 0;
2236}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002237
Laurence Lundblade1341c592020-04-11 14:19:05 -07002238
2239QCBORError QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2240{
2241 QCBORItem One[2];
2242
2243 One[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2244 One[0].label.string = UsefulBuf_FromSZ(szLabel);
2245 One[1].uLabelType = QCBOR_TYPE_NONE;
2246
2247 size_t uOffset;
2248
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002249 QCBORError nReturn = GetItemsInMap(pMe, One, &uOffset, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002250
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002251 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002252 return nReturn;
2253 }
2254
2255 if(One[0].uDataType != QCBOR_TYPE_ARRAY) {
2256 return QCBOR_ERR_UNEXPECTED_TYPE;
2257 }
2258
2259 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
2260
2261 QCBORItem ArrayToEnter;
2262 QCBORDecode_GetNext(pMe, &ArrayToEnter);
2263
2264
2265 // DecodeNesting_Descend(&(pMe->nesting), &One[1]);
2266
2267 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2268 pMe->nesting.pCurrent->uMapMode = 1;
2269 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
2270
2271 printdecode(pMe, "Entered Array in Map");
2272
2273 return 0;
2274}
2275
2276
2277
2278
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002279/* Next item must be map or this generates an error */
2280QCBORError QCBORDecode_EnterMap(QCBORDecodeContext *pMe)
2281{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002282 QCBORItem Item;
2283 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002284
2285 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002286 nReturn = QCBORDecode_GetNext(pMe, &Item);
2287 if(nReturn != QCBOR_SUCCESS) {
2288 return nReturn;
2289 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002290 if(Item.uDataType != QCBOR_TYPE_MAP) {
2291 return QCBOR_ERR_UNEXPECTED_TYPE;
2292 }
2293
Laurence Lundblade1341c592020-04-11 14:19:05 -07002294
2295 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
2296 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2297 pMe->nesting.pCurrent->uMapMode = 1;
2298 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002299
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002300 printdecode(pMe, "EnterMapDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002301
Laurence Lundblade1341c592020-04-11 14:19:05 -07002302 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002303}
2304
2305
2306
2307QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2308{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002309 return GetItemsInMap(pCtx, pItemList, NULL, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002310}
2311
2312
2313void QCBORDecode_GetIntInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, int64_t *pInt)
2314{
2315 // TODO: error handling
2316 QCBORItem Item;
2317 QCBORDecode_GetItemInMapSZ(pMe,szLabel, QCBOR_TYPE_INT64, &Item);
2318 *pInt = Item.val.int64;
2319}
2320
2321
Laurence Lundblade1341c592020-04-11 14:19:05 -07002322void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002323{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002324 // TODO: check for map mode
2325 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2326 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2327}
2328
2329
2330QCBORError QCBORDecode_EnterArray(QCBORDecodeContext *pMe)
2331{
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002332 QCBORItem Item;
2333 QCBORError nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002334
2335 /* Get the data item that is the map that is being searched */
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002336 nReturn = QCBORDecode_GetNext(pMe, &Item);
2337 if(nReturn != QCBOR_SUCCESS) {
2338 return nReturn;
2339 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002340 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
2341 return QCBOR_ERR_UNEXPECTED_TYPE;
2342 }
2343
2344 printdecode(pMe, "EnterArray");
2345
2346 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
2347 pMe->nesting.pCurrent->uOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2348 pMe->nesting.pCurrent->uMapMode = 1;
2349 pMe->nesting.pCurrent->uSaveCount = pMe->nesting.pCurrent->uCount;
2350
2351
2352 return QCBOR_SUCCESS;
2353}
2354
2355
2356void QCBORDecode_ExitArray(QCBORDecodeContext *pMe)
2357{
2358 // TODO: make sure we have entered an array
2359 // TODO: combine with code for map? It is the same so far.
2360 size_t uEndOffset;
2361
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002362 /* if(pMe->uMapEndOffset) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002363 uEndOffset = pMe->uMapEndOffset;
2364 // It is only valid once.
2365 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002366 } else {*/
Laurence Lundblade1341c592020-04-11 14:19:05 -07002367 QCBORItem Dummy;
2368
2369 Dummy.uLabelType = QCBOR_TYPE_NONE;
2370
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002371 QCBORError nReturn = GetItemsInMap(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002372
2373 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002374 //}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002375
Laurence Lundblade1341c592020-04-11 14:19:05 -07002376 printdecode(pMe, "start exit");
2377 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2378
2379 if(pMe->nesting.pCurrent->uCount != UINT16_MAX) {
2380 pMe->nesting.pCurrent->uCount = 1;
2381 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002382 pMe->nesting.pCurrent->uMapMode = 0;
2383 DecodeNesting_DecrementCount(&(pMe->nesting), true);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002384 printdecode(pMe, "end exit");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002385}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002386
Laurence Lundbladee6430642020-03-14 21:15:44 -07002387
2388
Laurence Lundbladec4537442020-04-14 18:53:22 -07002389void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002390{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002391 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002392 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07002393 return;
2394 }
2395
Laurence Lundbladec4537442020-04-14 18:53:22 -07002396 QCBORError nError;
2397 QCBORItem Item;
2398
2399 nError = QCBORDecode_GetNext(pMe, &Item);
2400 if(nError != QCBOR_SUCCESS) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002401 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002402 return;
2403 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002404
2405 switch(Item.uDataType) {
2406 case QCBOR_TYPE_TRUE:
2407 *pValue = true;
2408 break;
2409
2410 case QCBOR_TYPE_FALSE:
2411 *pValue = false;
2412 break;
2413
2414 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002415 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002416 break;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002417 }
2418}
2419
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002420#if 0
2421// TODO: fix this
Laurence Lundbladee6430642020-03-14 21:15:44 -07002422/* Types of text strings
2423 * Plain, b64, b64url, URI, regex, MIME Text
2424 * One function for each with options to expect plain?
2425 * One function for all so you can say what you want?
Laurence Lundbladec4537442020-04-14 18:53:22 -07002426 *
2427 * A label is expected if pLabel is not NULL.
Laurence Lundbladee6430642020-03-14 21:15:44 -07002428 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002429void QCBORDecode_GetTextFoo(QCBORDecodeContext *pMe, QCBORLabel *pLabel, UsefulBufC *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002430{
2431 QCBORItem Item;
2432 QCBORError nError;
2433
2434 nError = QCBORDecode_GetNext(pMe, &Item);
2435 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002436 pMe->uLastError = nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002437 return;
2438 }
2439
Laurence Lundbladec4537442020-04-14 18:53:22 -07002440 if(pLabel != NULL) {
2441 if(Item.uLabelType == QCBOR_TYPE_NONE) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002442 pMe->uLastError = 9; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07002443 return;
2444 } else {
2445 // TODO: what about label allocation?
2446 pLabel->uLabelType = Item.uLabelType;
2447 pLabel->label.xx = Item.label.int64; // TOOD: figure out assignment
2448 }
2449 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07002450
2451 switch(Item.uDataType) {
2452 case QCBOR_TYPE_TEXT_STRING:
2453 *pValue = Item.val.string;
2454 break;
2455
2456 default:
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002457 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002458 }
2459}
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002460#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002461
2462
Laurence Lundbladec4537442020-04-14 18:53:22 -07002463/*
2464 Options for MIME data, CBOR, positive big num, negative big num ??
2465 */
2466void QCBORDecode_GetStringInternal(QCBORDecodeContext *pMe, UsefulBufC *pValue, uint8_t uType)
2467{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002468 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002469 // Already in error state, do nothing
2470 return;
2471 }
2472
2473 QCBORError nError;
2474 QCBORItem Item;
2475
2476 nError = QCBORDecode_GetNext(pMe, &Item);
2477 if(nError != QCBOR_SUCCESS) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002478 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002479 return;
2480 }
2481
2482 if(Item.uDataType == uType) {
2483 *pValue = Item.val.string;
2484 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002485 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002486 }
2487}
2488
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002489void QCBORDecode_GetBytes(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002490{
2491 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_BYTE_STRING);
2492}
2493
2494
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002495void QCBORDecode_GetText(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002496{
2497 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_TEXT_STRING);
2498}
2499
2500
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002501void QCBORDecode_GetPosBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002502{
2503 // TODO: do these have to be tagged?
2504 // Probably should allow tagged or untagged, but not wrong-tagged
2505 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_POSBIGNUM);
2506}
2507
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002508void QCBORDecode_GetNegBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002509{
2510 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_NEGBIGNUM);
2511}
2512
2513
2514
Laurence Lundbladee6430642020-03-14 21:15:44 -07002515
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002516typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002517
2518
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002519// The main exponentiator that works on only positive numbers
2520static QCBORError Exponentitate10UU(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002521{
2522 uint64_t uResult;
2523
2524 uResult = uMantissa;
2525
2526 /* This loop will run a maximum of 19 times because
2527 * UINT64_MAX < 10 ^^ 19. More than that will cause
2528 * exit with the overflow error
2529 */
2530 while(nExponent > 0) {
2531 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002532 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladec4537442020-04-14 18:53:22 -07002533 }
2534 uResult = uResult * 10;
2535 nExponent--;
2536 }
2537
2538 while(nExponent < 0 ) {
2539 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002540 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
Laurence Lundbladec4537442020-04-14 18:53:22 -07002541 }
2542 uResult = uResult / 10;
2543 nExponent--;
2544 }
2545
2546 *puResult = uResult;
2547
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002548 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002549}
2550
2551
Laurence Lundbladee6430642020-03-14 21:15:44 -07002552/* Convert a decimal fraction to an int64_t without using
2553 floating point or math libraries. Most decimal fractions
2554 will not fit in an int64_t and this will error out with
2555 under or overflow
2556 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002557static QCBORError Exponentitate2UU(uint64_t nMantissa, int64_t nExponent, uint64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002558{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002559 uint64_t nResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002560
2561 nResult = nMantissa;
2562
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002563 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07002564 * INT64_MAX < 2^31. More than that will cause
2565 * exist with the overflow error
2566 */
2567 while(nExponent > 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002568 if(nResult > UINT64_MAX >> 1) {
2569 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07002570 }
2571 nResult = nResult << 1;
2572 nExponent--;
2573 }
2574
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002575 while(nExponent < 0 ) {
2576 if(nResult == 0) {
2577 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
2578 }
2579 nResult = nResult >> 1;
2580 nExponent--;
2581 }
2582
Laurence Lundbladee6430642020-03-14 21:15:44 -07002583 *pnResult = nResult;
2584
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002585 return QCBOR_SUCCESS;
2586}
2587
2588
2589static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2590{
2591 uint64_t uResult;
2592
2593 // Take the absolute value of the mantissa
2594 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
2595
2596 // Do the exponentiation of the positive mantissa
2597 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
2598 if(uReturn) {
2599 return uReturn;
2600 }
2601
2602 // Error out if too large on the plus side for an int64_t
2603 if(uResult > INT64_MAX) {
2604 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2605 }
2606
2607 // Error out if too large on the negative side for an int64_t
2608 if(uResult < (uint64_t)INT64_MAX+1) {
2609 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
2610 of INT64_MIN. This assumes two's compliment representation where
2611 INT64_MIN is one increment farther from 0 than INT64_MAX.
2612 Trying to write -INT64_MIN doesn't work to get this because the
2613 compiler tries to work with an int64_t which can't represent
2614 -INT64_MIN.
2615 */
2616 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2617 }
2618
2619 // Casts are safe because of checks above
2620 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
2621
2622 return QCBOR_SUCCESS;
2623}
2624
2625
2626static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
2627{
2628 if(nMantissa < 0) {
2629 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
2630 }
2631
2632 // Cast to unsigned is OK because of check for negative
2633 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
2634 // Exponentiation is straight forward
2635 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
2636}
2637
2638
2639// TODO: use this or get rid of it
2640QCBORError ExponentitateUN(uint64_t uMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2641{
2642 uint64_t uResult;
2643
2644 QCBORError uR;
2645
2646 uR = (*pfExp)(uMantissa, nExponent, &uResult);
2647 if(uR) {
2648 return uR;
2649 }
2650
2651 if(uResult > INT64_MAX) {
2652 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2653 }
2654
2655 // Cast is OK because of check above
2656 *pnResult = (int64_t)uResult;
2657
2658 return QCBOR_SUCCESS;
2659}
2660
2661
2662
2663
2664#include <math.h>
2665/*
2666static inline uint8_t Exponentitate10F(uint64_t uMantissa, int64_t nExponent, double *pfResult)
2667{
2668 // TODO: checkout exceptions; what is HUGE_VAL?
2669 *pfResult = pow((double)10, (double)nExponent) * (double)uMantissa;
2670
2671 //if(*pfResult == HUGE_VAL)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002672 return 0;
2673}
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002674*/
2675
2676
2677
2678
2679
Laurence Lundbladee6430642020-03-14 21:15:44 -07002680
2681/*
2682 A) bignum is positive
2683 A1) output is signed INT64_MAX
2684 A2) output is unsigned UINT64_MAX
2685 B) bignum is negative
2686 B1) output is signed INT64_MAX
2687 B2) output is unsigned error
2688 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002689static inline QCBORError ConvertBigNum(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002690{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002691 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002692
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002693 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002694 const uint8_t *pByte = BigNum.ptr;
2695 size_t uLen = BigNum.len;
2696 while(uLen--) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002697 if(uResult > uMax >> 8) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002698 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002699 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002700 uResult = (uResult << 8) + *pByte;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002701 }
2702
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002703 *pResult = uResult;
2704 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002705}
2706
Laurence Lundbladec4537442020-04-14 18:53:22 -07002707
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002708#if 0
2709static inline QCBORError ConvertBigNumToDouble(const UsefulBufC BigNum, uint64_t uMax, double *pResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002710{
2711 double nResult;
2712
2713 nResult = 0;
2714 const uint8_t *pByte = BigNum.ptr;
2715 size_t uLen = BigNum.len;
2716 /* This will overflow and become the float value INFINITY if the number
2717 is too large to fit. No error will be logged.
2718 TODO: should an error be logged? */
2719 while(uLen--) {
2720 nResult = (nResult * 256) + *pByte;
2721 }
2722
2723 *pResult = nResult;
2724 return 0;
2725}
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002726#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07002727
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002728static inline QCBORError ConvertPositiveBigNumToUnSigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002729{
2730 return ConvertBigNum(BigNum, UINT64_MAX, pResult);
2731}
2732
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002733static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002734{
2735 uint64_t uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002736 QCBORError n = ConvertBigNum(BigNum, INT64_MAX, &uResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002737 if(n) {
2738 return n;
2739 }
2740 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2741 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002742 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002743}
2744
2745
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002746static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002747{
2748 uint64_t uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002749 QCBORError n = ConvertBigNum(BigNum, INT64_MAX-1, &uResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002750 if(n) {
2751 return n;
2752 }
2753 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2754 *pResult = -(int64_t)uResult;
2755 return 0;
2756}
2757
Laurence Lundbladec4537442020-04-14 18:53:22 -07002758// No function to convert a negative bignum to unsigned; it is an error
2759
2760
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002761#if 0
2762static inline int ConvertXYZ(const UsefulBufC Mantissa, int64_t nExponent, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002763{
2764 int64_t nMantissa;
2765
2766 int xx = ConvertPositiveBigNumToSigned(Mantissa, &nMantissa);
2767 if(xx) {
2768 return xx;
2769 }
2770
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002771 return ExponentiateNN(nMantissa, nExponent, pResult, &Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002772}
2773
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002774#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002775
2776
Laurence Lundbladee6430642020-03-14 21:15:44 -07002777
Laurence Lundbladec4537442020-04-14 18:53:22 -07002778
2779/*
2780 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2781 a big float, a decimal fraction or a big num. Conversion will be dones as
2782 expected. Some cases will error out with under or over flow.
2783 */
2784void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue, QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002785{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002786 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002787 return;
2788 }
2789
Laurence Lundbladee6430642020-03-14 21:15:44 -07002790 QCBORItem Item;
2791 QCBORError nError;
2792
2793 nError = QCBORDecode_GetNext(pMe, &Item);
2794 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002795 pMe->uLastError = nError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002796 return;
2797 }
2798
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002799 if(pItem) {
2800 *pItem = Item;
2801 }
2802
Laurence Lundbladee6430642020-03-14 21:15:44 -07002803 switch(Item.uDataType) {
2804 case QCBOR_TYPE_FLOAT:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002805 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002806 // TODO: what about under/overflow here?
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002807 // Invokes the floating-point HW and/or compiler-added libraries
Laurence Lundbladee6430642020-03-14 21:15:44 -07002808 *pValue = (int64_t)Item.val.dfnum;
2809 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002810 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002811 }
2812 break;
2813
2814 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002815 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002816 *pValue = Item.val.int64;
2817 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002818 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002819 }
2820 break;
2821
2822 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002823 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002824 if(Item.val.uint64 < INT64_MAX) {
2825 *pValue = Item.val.int64;
2826 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002827 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002828 }
2829 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002830 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002831 }
2832 break;
2833
Laurence Lundbladec4537442020-04-14 18:53:22 -07002834 default:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002835 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002836 }
2837}
2838
2839/* This works for signed, unsigned and float */
2840void QCBORDecode_GetInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2841{
2842 QCBORItem Item;
2843 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2844}
2845
2846
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002847// TODO make this inline
2848void QCBORDecode_GetInt64(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2849{
2850 QCBORDecode_GetInt64Convert(pMe, QCBOR_TYPE_INT64, pValue);
2851}
2852
2853
Laurence Lundbladec4537442020-04-14 18:53:22 -07002854
2855/*
2856 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2857 a big float, a decimal fraction or a big num. Conversion will be dones as
2858 expected. Some cases will error out with under or over flow.
2859 */
2860void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2861{
2862 QCBORItem Item;
2863
2864 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2865
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002866 if(pMe->uLastError == QCBOR_SUCCESS) {
2867 // The above conversion succeeded
2868 return;
2869 }
2870
2871 if(pMe->uLastError != QCBOR_SUCCESS && pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
2872 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07002873 return;
2874 }
2875
2876 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002877
2878 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002879 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002880 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002881 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002882 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002883 }
2884 break;
2885
2886 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002887 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002888 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002889 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002890 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002891 }
2892 break;
2893
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002894#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2895 case QCBOR_TYPE_DECIMAL_FRACTION:
2896 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
2897 pMe->uLastError = ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
2898 Item.val.expAndMantissa.nExponent,
2899 pValue,
2900 &Exponentitate10UU);
2901 } else {
2902 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2903 }
2904 break;
2905
2906 case QCBOR_TYPE_BIGFLOAT:
2907 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
2908 pMe->uLastError = ExponentiateNN(Item.val.expAndMantissa.Mantissa.nInt,
2909 Item.val.expAndMantissa.nExponent,
2910 pValue,
2911 &Exponentitate2UU);
2912 } else {
2913 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2914 }
2915 break;
2916
2917
Laurence Lundbladee6430642020-03-14 21:15:44 -07002918 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002919 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002920 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002921 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2922 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002923 pMe->uLastError = ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002924 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002925 pValue,
2926 &Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002927 }
2928 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002929 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002930 }
2931 break;
2932
2933 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002934 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002935 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002936 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2937 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002938 pMe->uLastError = ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002939 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002940 pValue,
2941 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002942 }
2943 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002944 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002945 }
2946 break;
2947
2948 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002949 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002950 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002951 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2952 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002953 pMe->uLastError = ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002954 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002955 pValue,
2956 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002957 }
2958 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002959 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002960 }
2961 break;
2962
2963 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002964 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002965 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002966 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2967 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002968 pMe->uLastError = ExponentiateNN(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07002969 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002970 pValue,
2971 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002972 }
2973 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002974 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002975 }
2976 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002977
2978 default:
2979 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2980#endif
Laurence Lundbladee6430642020-03-14 21:15:44 -07002981 }
2982}
2983
Laurence Lundbladec4537442020-04-14 18:53:22 -07002984
2985
2986void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue, QCBORItem *pItem)
2987{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002988 if(pMe->uLastError != QCBOR_SUCCESS) {
2989 return;
2990 }
2991
Laurence Lundbladec4537442020-04-14 18:53:22 -07002992 QCBORItem Item;
2993 QCBORError nError;
2994
2995 nError = QCBORDecode_GetNext(pMe, &Item);
2996 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002997 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002998 return;
2999 }
3000
3001 switch(Item.uDataType) {
3002 case QCBOR_TYPE_FLOAT:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003003 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003004 if(Item.val.dfnum >= 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003005 // TODO: over/underflow
Laurence Lundbladec4537442020-04-14 18:53:22 -07003006 *pValue = (uint64_t)Item.val.dfnum;
3007 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003008 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003009 }
3010 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003011 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003012 }
3013 break;
3014
3015 case QCBOR_TYPE_INT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003016 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003017 if(Item.val.int64 >= 0) {
3018 *pValue = (uint64_t)Item.val.int64;
3019 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003020 pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003021 }
3022 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003023 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003024 }
3025 break;
3026
3027 case QCBOR_TYPE_UINT64:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003028 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003029 *pValue = Item.val.uint64;
3030 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003031 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003032 }
3033 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003034
3035 default:
3036 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003037 }
3038}
3039
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003040
3041/* This works for signed, unsigned and float */
3042void QCBORDecode_GetUInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003043{
3044 QCBORItem Item;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003045 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
3046}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003047
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003048
3049// TODO make this inline
3050void QCBORDecode_GetUInt64(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
3051{
3052 QCBORDecode_GetUInt64Convert(pMe, QCBOR_TYPE_UINT64, pValue);
3053}
3054
3055
3056
3057
3058void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
3059{
3060 QCBORItem Item;
3061
3062 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
3063
3064 if(pMe->uLastError != QCBOR_SUCCESS && pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003065 return;
3066 }
3067
Laurence Lundbladee6430642020-03-14 21:15:44 -07003068 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003069
3070 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003071 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3072 pMe->uLastError = ConvertPositiveBigNumToUnSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003073 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003074 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003075 }
3076 break;
3077
3078 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003079 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3080 pMe->uLastError = ConvertPositiveBigNumToUnSigned(Item.val.bigNum, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003081 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003082 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003083 }
3084 break;
3085
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003086#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3087
3088 case QCBOR_TYPE_DECIMAL_FRACTION:
3089 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3090 pMe->uLastError = ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
3091 Item.val.expAndMantissa.nExponent,
3092 pValue,
3093 Exponentitate10UU);
3094 } else {
3095 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
3096 }
3097 break;
3098
3099 case QCBOR_TYPE_BIGFLOAT:
3100 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3101 pMe->uLastError = ExponentitateNU(Item.val.expAndMantissa.Mantissa.nInt,
3102 Item.val.expAndMantissa.nExponent,
3103 pValue,
3104 Exponentitate2UU);
3105 } else {
3106 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
3107 }
3108 break;
3109
3110
3111
Laurence Lundbladee6430642020-03-14 21:15:44 -07003112 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003113 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003114 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003115 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3116 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003117 pMe->uLastError = ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003118 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003119 pValue,
3120 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003121 }
3122 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003123 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003124 }
3125 break;
3126
3127 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003128 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003129 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003130 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3131 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003132 pMe->uLastError = ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003133 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003134 pValue,
3135 Exponentitate10UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003136 }
3137 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003138 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003139 }
3140 break;
3141
3142 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003143 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003144 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003145 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3146 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003147 pMe->uLastError = ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003148 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003149 pValue,
3150 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003151 }
3152 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003153 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
Laurence Lundbladee6430642020-03-14 21:15:44 -07003154 }
3155 break;
3156
3157 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003158 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07003159 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003160 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3161 if(!pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003162 pMe->uLastError = ExponentitateNU(nMantissa,
Laurence Lundbladee6430642020-03-14 21:15:44 -07003163 Item.val.expAndMantissa.nExponent,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003164 pValue,
3165 Exponentitate2UU);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003166 }
3167 } else {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003168 pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003169 }
3170 break;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003171#endif
3172 default:
3173 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003174 }
3175}
3176
Laurence Lundbladec4537442020-04-14 18:53:22 -07003177
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003178
3179#if 0
Laurence Lundbladec4537442020-04-14 18:53:22 -07003180/*
3181
3182 Convert from bignums,
3183
3184 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003185void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003186{
3187 /* the same range of conversions */
3188
Laurence Lundbladec4537442020-04-14 18:53:22 -07003189 /* Conversion from bignums, decimal fractions and such will be interesting */
3190
3191 QCBORItem Item;
3192 QCBORError nError;
3193
3194 nError = QCBORDecode_GetNext(pMe, &Item);
3195 if(nError) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003196 pMe->uLastError = nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003197 return;
3198 }
3199
Laurence Lundbladec4537442020-04-14 18:53:22 -07003200
3201 switch(Item.uDataType) {
3202 case QCBOR_TYPE_FLOAT:
3203 if(uOptions & QCBOR_DECODE_TYPE_FLOAT) {
3204 *pValue = Item.val.dfnum;
3205 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003206 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003207 }
3208 break;
3209
3210 case QCBOR_TYPE_INT64:
3211 if(uOptions & QCBOR_DECODE_TYPE_INT64) {
3212 // TODO: how does this work?
3213 *pValue = (double)Item.val.int64;
3214 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003215 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003216 }
3217 break;
3218
3219 case QCBOR_TYPE_UINT64:
3220 if(uOptions & QCBOR_DECODE_TYPE_UINT64) {
3221 *pValue = (double)Item.val.uint64;
3222 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003223 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003224 }
3225 break;
3226
3227 case QCBOR_TYPE_DECIMAL_FRACTION:
3228 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003229 pMe->uLastError = Exponentitate10(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003230 Item.val.expAndMantissa.nExponent,
3231 pValue);
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_BIGFLOAT:
3238 if(uOptions & QCBOR_DECODE_TYPE_BIGFLOAT) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003239 pMe->uLastError = Exponentitate2(Item.val.expAndMantissa.Mantissa.nInt,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003240 Item.val.expAndMantissa.nExponent,
3241 pValue);
3242 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003243 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003244 }
3245 break;
3246
3247 case QCBOR_TYPE_POSBIGNUM:
3248 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003249 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003250 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003251 pMe->uLastError = 99;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003252 }
3253 break;
3254
3255 case QCBOR_TYPE_NEGBIGNUM:
3256 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003257 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003258 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003259 pMe->uLastError = 99;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003260 }
3261 break;
3262
3263 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3264 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3265 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003266 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3267 if(!pMe->uLastError) {
3268 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003269 Item.val.expAndMantissa.nExponent,
3270 pValue);
3271 }
3272 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003273 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003274 }
3275 break;
3276
3277 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3278 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3279 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003280 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3281 if(!pMe->uLastError) {
3282 pMe->uLastError = Exponentitate10(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003283 Item.val.expAndMantissa.nExponent,
3284 pValue);
3285 }
3286 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003287 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003288 }
3289 break;
3290
3291 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3292 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3293 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003294 pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3295 if(!pMe->uLastError) {
3296 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003297 Item.val.expAndMantissa.nExponent,
3298 pValue);
3299 }
3300 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003301 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003302 }
3303 break;
3304
3305 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3306 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
3307 int64_t nMantissa;
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003308 pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3309 if(!pMe->uLastError) {
3310 pMe->uLastError = Exponentitate2(nMantissa,
Laurence Lundbladec4537442020-04-14 18:53:22 -07003311 Item.val.expAndMantissa.nExponent,
3312 pValue);
3313 }
3314 } else {
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003315 pMe->uLastError = 99; // TODO: error code
Laurence Lundbladec4537442020-04-14 18:53:22 -07003316 }
3317 break;
3318 }
3319
3320
3321
Laurence Lundbladee6430642020-03-14 21:15:44 -07003322}
3323
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003324#endif