Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1 | /*============================================================================== |
Laurence Lundblade | d92a616 | 2018-11-01 11:38:35 +0700 | [diff] [blame] | 2 | Copyright (c) 2016-2018, The Linux Foundation. |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 3 | Copyright (c) 2018-2020, Laurence Lundblade. |
Laurence Lundblade | d92a616 | 2018-11-01 11:38:35 +0700 | [diff] [blame] | 4 | All rights reserved. |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 5 | |
Laurence Lundblade | 0dbc917 | 2018-11-01 14:17:21 +0700 | [diff] [blame] | 6 | Redistribution and use in source and binary forms, with or without |
| 7 | modification, are permitted provided that the following conditions are |
| 8 | met: |
| 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 Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 19 | |
Laurence Lundblade | 0dbc917 | 2018-11-01 14:17:21 +0700 | [diff] [blame] | 20 | THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| 21 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| 23 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| 24 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 25 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 26 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| 27 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 28 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| 29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| 30 | IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 31 | =============================================================================*/ |
Laurence Lundblade | 624405d | 2018-09-18 20:10:47 -0700 | [diff] [blame] | 32 | |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 33 | |
Laurence Lundblade | 844bb5c | 2020-03-01 17:27:25 -0800 | [diff] [blame] | 34 | #include "qcbor/qcbor_decode.h" |
Laurence Lundblade | 12d32c5 | 2018-09-19 11:25:27 -0700 | [diff] [blame] | 35 | #include "ieee754.h" |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 36 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 37 | |
Laurence Lundblade | 7e0d13b | 2018-10-16 19:54:13 +0530 | [diff] [blame] | 38 | /* |
| 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 Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 44 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 45 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 46 | /*=========================================================================== |
| 47 | DecodeNesting -- Functions for tracking array/map nesting when decoding |
| 48 | |
Laurence Lundblade | 844bb5c | 2020-03-01 17:27:25 -0800 | [diff] [blame] | 49 | See qcbor/qcbor_decode.h for definition of the object |
| 50 | used here: QCBORDecodeNesting |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 51 | ===========================================================================*/ |
| 52 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 53 | |
| 54 | |
| 55 | /* |
| 56 | The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...) |
| 57 | formed 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 | |
| 65 | The 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 | |
| 101 | When 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 Lundblade | 6b24930 | 2020-04-30 12:38:12 -0700 | [diff] [blame] | 115 | inline static bool |
| 116 | // TODO: test Map as array better? |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 117 | IsMapOrArray(uint8_t uDataType) |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 118 | { |
Laurence Lundblade | 6b24930 | 2020-04-30 12:38:12 -0700 | [diff] [blame] | 119 | return uDataType == QCBOR_TYPE_MAP || |
| 120 | uDataType == QCBOR_TYPE_ARRAY || |
| 121 | uDataType == QCBOR_TYPE_MAP_AS_ARRAY; |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 122 | } |
| 123 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 124 | |
| 125 | inline static uint8_t |
| 126 | DecodeNesting_GetLevel(const QCBORDecodeNesting *pNesting) |
| 127 | { |
Laurence Lundblade | 5e87da6 | 2020-06-07 03:24:28 -0700 | [diff] [blame] | 128 | const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]); |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 129 | // Check in DecodeNesting_Descend and never having |
| 130 | // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe |
Laurence Lundblade | 5e87da6 | 2020-06-07 03:24:28 -0700 | [diff] [blame] | 131 | return (uint8_t)nLevel; |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 132 | } |
| 133 | |
| 134 | |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 135 | inline static bool DecodeNesting_InBoundedMode(const QCBORDecodeNesting *pNesting) |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 136 | { |
| 137 | return pNesting->pCurrent->uType & QCBOR_NEST_TYPE_IS_BOUND; |
| 138 | } |
| 139 | |
| 140 | /*inline static bool IsArray(const QCBORDecodeNesting *pNesting) |
| 141 | { |
| 142 | const unsigned uIndex = DecodeNesting_GetLevel(pNesting); |
| 143 | |
| 144 | return (0x01ULL << ((uIndex * 3) + 1)) & pNesting->uTypeBitMap; |
| 145 | } |
| 146 | |
| 147 | inline static bool IsBstr(const QCBORDecodeNesting *pNesting) |
| 148 | { |
| 149 | const unsigned uIndex = DecodeNesting_GetLevel(pNesting); |
| 150 | |
| 151 | return (0x01ULL << ((uIndex * 3) + 2)) & pNesting->uTypeBitMap; |
| 152 | }*/ |
| 153 | |
| 154 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 155 | inline static bool |
| 156 | DecodeNesting_IsAtTop(const QCBORDecodeNesting *pNesting) |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 157 | { |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 158 | if(pNesting->pCurrent == &(pNesting->pMapsAndArrays[0])) { |
| 159 | return true; |
| 160 | } else { |
| 161 | return false; |
| 162 | } |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 163 | } |
| 164 | |
Laurence Lundblade | 937ea81 | 2020-05-08 11:38:23 -0700 | [diff] [blame] | 165 | // Determine if at the end of a map or array while in map mode |
Laurence Lundblade | 3f9ef04 | 2020-04-14 13:15:51 -0700 | [diff] [blame] | 166 | inline static bool |
| 167 | DecodeNesting_AtEnd(const QCBORDecodeNesting *pNesting) |
| 168 | { |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 169 | if(pNesting->pCurrentMap && DecodeNesting_InBoundedMode(pNesting)) { |
Laurence Lundblade | 64b607e | 2020-05-13 13:05:57 -0700 | [diff] [blame] | 170 | if(pNesting->pCurrentMap->uCount == 0) { |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 171 | // In map mode and consumed all items, so it is the end |
| 172 | return true; |
| 173 | } else { |
| 174 | // In map mode, all items not consumed, so it is NOT the end |
| 175 | return false; |
| 176 | } |
| 177 | } else { |
Laurence Lundblade | 937ea81 | 2020-05-08 11:38:23 -0700 | [diff] [blame] | 178 | // Not in map mode. The end is determined in other ways. |
Laurence Lundblade | 3f9ef04 | 2020-04-14 13:15:51 -0700 | [diff] [blame] | 179 | return false; |
| 180 | } |
Laurence Lundblade | 3f9ef04 | 2020-04-14 13:15:51 -0700 | [diff] [blame] | 181 | } |
| 182 | |
| 183 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 184 | inline static int |
| 185 | DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting) |
Laurence Lundblade | 0f99d69 | 2018-09-26 14:39:28 -0700 | [diff] [blame] | 186 | { |
Laurence Lundblade | 0f99d69 | 2018-09-26 14:39:28 -0700 | [diff] [blame] | 187 | return pNesting->pCurrent->uCount == UINT16_MAX; |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 188 | //return pNesting->pCurrent->uType & QCBOR_NEST_TYPE_IS_INDEFINITE; |
Laurence Lundblade | 0f99d69 | 2018-09-26 14:39:28 -0700 | [diff] [blame] | 189 | } |
| 190 | |
Laurence Lundblade | 3a760b0 | 2018-10-08 13:46:03 +0800 | [diff] [blame] | 191 | |
Laurence Lundblade | 64b607e | 2020-05-13 13:05:57 -0700 | [diff] [blame] | 192 | inline static uint8_t |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 193 | DecodeNesting_GetBoundedModeLevel(QCBORDecodeNesting *pNesting) |
Laurence Lundblade | 64b607e | 2020-05-13 13:05:57 -0700 | [diff] [blame] | 194 | { |
| 195 | // Check in DecodeNesting_Descend and never having |
| 196 | // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe |
| 197 | return (uint8_t)(pNesting->pCurrentMap - &(pNesting->pMapsAndArrays[0])); |
| 198 | } |
| 199 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 200 | inline static int |
| 201 | DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting) |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 202 | { |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 203 | if(DecodeNesting_IsAtTop(pNesting)) { |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 204 | return 0; |
Laurence Lundblade | 0f99d69 | 2018-09-26 14:39:28 -0700 | [diff] [blame] | 205 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 206 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 207 | return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType; |
| 208 | } |
| 209 | |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 210 | inline static bool |
| 211 | DecodeNesting_BoundedIsType(const QCBORDecodeNesting *pNesting, uint8_t uType) |
| 212 | { |
| 213 | if(pNesting->pCurrentMap->uMajorType == uType) { |
| 214 | return true; |
| 215 | } else { |
| 216 | return false; |
| 217 | } |
| 218 | } |
| 219 | |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 220 | |
| 221 | // return 1 if closed out an array or map |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 222 | inline static void |
| 223 | DecodeNesting_DecrementX(QCBORDecodeNesting *pNesting) |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 224 | { |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 225 | pNesting->pCurrent->uCount--; |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 226 | } |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 227 | |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 228 | inline static bool |
| 229 | DecodeNesting_IsEndOfDefiniteLengthMapOrArray(QCBORDecodeNesting *pNesting) |
| 230 | { |
| 231 | if(pNesting->pCurrent->uCount == 0) { |
| 232 | return true; |
| 233 | } else { |
| 234 | return false; |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 235 | } |
Laurence Lundblade | 3a760b0 | 2018-10-08 13:46:03 +0800 | [diff] [blame] | 236 | } |
| 237 | |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 238 | inline static void |
| 239 | DecodeNesting_Ascend(QCBORDecodeNesting *pNesting) |
| 240 | { |
| 241 | pNesting->pCurrent--; |
| 242 | } |
| 243 | |
| 244 | |
Laurence Lundblade | 5e87da6 | 2020-06-07 03:24:28 -0700 | [diff] [blame] | 245 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 246 | |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 247 | inline static void |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 248 | DecodeNesting_EnterBoundedMode(QCBORDecodeNesting *pNesting, size_t uOffset) |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 249 | { |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 250 | /* Have descended into this is called. The job here is just to mark it in bounded mode */ |
Laurence Lundblade | 64b607e | 2020-05-13 13:05:57 -0700 | [diff] [blame] | 251 | pNesting->pCurrentMap = pNesting->pCurrent; |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 252 | pNesting->pCurrentMap->uType |= QCBOR_NEST_TYPE_IS_BOUND; |
| 253 | // Cast to uint32_t is safe because QCBOR restricts encoded input to < UINT32_MAX |
Laurence Lundblade | 64b607e | 2020-05-13 13:05:57 -0700 | [diff] [blame] | 254 | pNesting->pCurrentMap->uOffset = (uint32_t)uOffset; |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 255 | } |
| 256 | |
Laurence Lundblade | 64b607e | 2020-05-13 13:05:57 -0700 | [diff] [blame] | 257 | |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 258 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 259 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 260 | inline static QCBORError |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 261 | DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uQCBORType, uint64_t uCount, uint32_t uEndOffset) |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 262 | { |
| 263 | QCBORError nReturn = QCBOR_SUCCESS; |
| 264 | |
| 265 | if(uCount == 0) { |
| 266 | // Nothing to do for empty definite lenth arrays. They are just are |
| 267 | // effectively the same as an item that is not a map or array |
| 268 | goto Done; |
| 269 | // Empty indefinite length maps and arrays are handled elsewhere |
| 270 | } |
| 271 | |
| 272 | // Error out if arrays is too long to handle |
| 273 | if(uCount != UINT16_MAX && uCount > QCBOR_MAX_ITEMS_IN_ARRAY) { |
| 274 | nReturn = QCBOR_ERR_ARRAY_TOO_LONG; |
| 275 | goto Done; |
| 276 | } |
| 277 | |
| 278 | // Error out if nesting is too deep |
| 279 | if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) { |
| 280 | nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP; |
| 281 | goto Done; |
| 282 | } |
| 283 | |
| 284 | // The actual descend |
| 285 | pNesting->pCurrent++; |
| 286 | |
| 287 | // Fill in the new level fully |
| 288 | pNesting->pCurrent->uMajorType = uQCBORType; |
| 289 | pNesting->pCurrent->uCount = (uint16_t)uCount; |
| 290 | pNesting->pCurrent->uSaveCount = (uint16_t)uCount; |
| 291 | pNesting->pCurrent->uEndOffset = uEndOffset; |
| 292 | pNesting->pCurrent->uMapMode = 0; |
| 293 | |
| 294 | Done: |
| 295 | return nReturn;; |
| 296 | } |
| 297 | |
| 298 | |
| 299 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 300 | inline static void |
| 301 | DecodeNesting_Init(QCBORDecodeNesting *pNesting) |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 302 | { |
| 303 | pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]); |
| 304 | } |
| 305 | |
| 306 | |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 307 | static void DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave) |
| 308 | { |
| 309 | *pSave = *pNesting; |
| 310 | pNesting->pCurrent = pNesting->pCurrentMap; |
| 311 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 312 | if(!DecodeNesting_IsIndefiniteLength(pNesting)) { |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 313 | pNesting->pCurrent->uCount = pNesting->pCurrent->uSaveCount; |
| 314 | } |
| 315 | } |
| 316 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 317 | static inline void DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave) |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 318 | { |
| 319 | *pNesting = *pSave; |
| 320 | } |
| 321 | |
Laurence Lundblade | 5e87da6 | 2020-06-07 03:24:28 -0700 | [diff] [blame] | 322 | QCBORError DecodeNesting_EnterBstr(QCBORDecodeNesting *pNesting, uint32_t uEndOffset) |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 323 | { |
| 324 | QCBORError uReturn ; |
| 325 | |
| 326 | // Error out if nesting is too deep |
| 327 | if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) { |
| 328 | uReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP; |
| 329 | goto Done; |
| 330 | } |
| 331 | |
| 332 | // The actual descend |
| 333 | pNesting->pCurrent++; |
| 334 | |
| 335 | // Record a few details for this nesting level |
| 336 | pNesting->pCurrent->uMajorType = 1; // TODO the right value for a bstr |
| 337 | pNesting->pCurrent->uCount = 0xffff; |
| 338 | pNesting->pCurrent->uSaveCount = 0xffff; |
| 339 | pNesting->pCurrent->uType = 0; |
| 340 | |
| 341 | uReturn = QCBOR_SUCCESS; |
| 342 | |
| 343 | Done: |
| 344 | return uReturn; |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 345 | } |
| 346 | |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 347 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 348 | |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 349 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 350 | /*=========================================================================== |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 351 | QCBORStringAllocate -- STRING ALLOCATOR INVOCATION |
| 352 | |
| 353 | The following four functions are pretty wrappers for invocation of |
| 354 | the string allocator supplied by the caller. |
| 355 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 356 | ===========================================================================*/ |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 357 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 358 | static inline void |
| 359 | StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem) |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 360 | { |
| 361 | (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0); |
| 362 | } |
| 363 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 364 | // StringAllocator_Reallocate called with pMem NULL is |
| 365 | // equal to StringAllocator_Allocate() |
| 366 | static inline UsefulBuf |
| 367 | StringAllocator_Reallocate(const QCORInternalAllocator *pMe, |
| 368 | void *pMem, |
| 369 | size_t uSize) |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 370 | { |
| 371 | return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize); |
| 372 | } |
| 373 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 374 | static inline UsefulBuf |
| 375 | StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize) |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 376 | { |
| 377 | return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize); |
| 378 | } |
| 379 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 380 | static inline void |
| 381 | StringAllocator_Destruct(const QCORInternalAllocator *pMe) |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 382 | { |
| 383 | if(pMe->pfAllocator) { |
| 384 | (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0); |
| 385 | } |
| 386 | } |
| 387 | |
| 388 | |
| 389 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 390 | /*=========================================================================== |
| 391 | QCBORDecode -- The main implementation of CBOR decoding |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 392 | |
Laurence Lundblade | 844bb5c | 2020-03-01 17:27:25 -0800 | [diff] [blame] | 393 | See qcbor/qcbor_decode.h for definition of the object |
| 394 | used here: QCBORDecodeContext |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 395 | ===========================================================================*/ |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 396 | /* |
| 397 | Public function, see header file |
| 398 | */ |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 399 | void QCBORDecode_Init(QCBORDecodeContext *me, |
| 400 | UsefulBufC EncodedCBOR, |
| 401 | QCBORDecodeMode nDecodeMode) |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 402 | { |
| 403 | memset(me, 0, sizeof(QCBORDecodeContext)); |
| 404 | UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR); |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 405 | // Don't bother with error check on decode mode. If a bad value is |
| 406 | // passed it will just act as if the default normal mode of 0 was set. |
Laurence Lundblade | e6bcef1 | 2020-04-01 10:56:27 -0700 | [diff] [blame] | 407 | me->uDecodeMode = (uint8_t)nDecodeMode; |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 408 | DecodeNesting_Init(&(me->nesting)); |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 409 | for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) { |
Laurence Lundblade | c75e68b | 2020-06-15 20:34:46 -0700 | [diff] [blame] | 410 | me->auMappedTags[i] = CBOR_TAG_INVALID16; |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 411 | } |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 412 | } |
| 413 | |
| 414 | |
| 415 | /* |
Laurence Lundblade | 0f99d69 | 2018-09-26 14:39:28 -0700 | [diff] [blame] | 416 | Public function, see header file |
| 417 | */ |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 418 | void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe, |
| 419 | QCBORStringAllocate pfAllocateFunction, |
| 420 | void *pAllocateContext, |
| 421 | bool bAllStrings) |
Laurence Lundblade | 0f99d69 | 2018-09-26 14:39:28 -0700 | [diff] [blame] | 422 | { |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 423 | pMe->StringAllocator.pfAllocator = pfAllocateFunction; |
| 424 | pMe->StringAllocator.pAllocateCxt = pAllocateContext; |
| 425 | pMe->bStringAllocateAll = bAllStrings; |
Laurence Lundblade | 0f99d69 | 2018-09-26 14:39:28 -0700 | [diff] [blame] | 426 | } |
| 427 | |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 428 | |
| 429 | /* |
| 430 | Public function, see header file |
| 431 | */ |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 432 | void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me, |
| 433 | const QCBORTagListIn *pTagList) |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 434 | { |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 435 | // This does nothing now. It is retained for backwards compatibility |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 436 | } |
| 437 | |
Laurence Lundblade | 0f99d69 | 2018-09-26 14:39:28 -0700 | [diff] [blame] | 438 | |
| 439 | /* |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 440 | This decodes the fundamental part of a CBOR data item, the type and |
| 441 | number |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 442 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 443 | This is the Counterpart to InsertEncodedTypeAndNumber(). |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 444 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 445 | This does the network->host byte order conversion. The conversion |
| 446 | here also results in the conversion for floats in addition to that |
| 447 | for lengths, tags and integer values. |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 448 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 449 | This returns: |
| 450 | pnMajorType -- the major type for the item |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 451 | |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 452 | puArgument -- the "number" which is used a the value for integers, |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 453 | tags and floats and length for strings and arrays |
| 454 | |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 455 | pnAdditionalInfo -- Pass this along to know what kind of float or |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 456 | if length is indefinite |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 457 | |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 458 | The int type is preferred to uint8_t for some variables as this |
| 459 | avoids integer promotions, can reduce code size and makes |
| 460 | static analyzers happier. |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 461 | */ |
Laurence Lundblade | 4c0cf84 | 2019-01-12 03:25:44 -0800 | [diff] [blame] | 462 | inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, |
| 463 | int *pnMajorType, |
| 464 | uint64_t *puArgument, |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 465 | int *pnAdditionalInfo) |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 466 | { |
Laurence Lundblade | 30816f2 | 2018-11-10 13:40:22 +0700 | [diff] [blame] | 467 | QCBORError nReturn; |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 468 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 469 | // Get the initial byte that every CBOR data item has |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 470 | const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf); |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 471 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 472 | // Break down the initial byte |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 473 | const int nTmpMajorType = nInitialByte >> 5; |
| 474 | const int nAdditionalInfo = nInitialByte & 0x1f; |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 475 | |
Laurence Lundblade | 4c0cf84 | 2019-01-12 03:25:44 -0800 | [diff] [blame] | 476 | // Where the number or argument accumulates |
| 477 | uint64_t uArgument; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 478 | |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 479 | if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) { |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 480 | // Need to get 1,2,4 or 8 additional argument bytes. Map |
| 481 | // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length |
Laurence Lundblade | 4c0cf84 | 2019-01-12 03:25:44 -0800 | [diff] [blame] | 482 | static const uint8_t aIterate[] = {1,2,4,8}; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 483 | |
Laurence Lundblade | 4c0cf84 | 2019-01-12 03:25:44 -0800 | [diff] [blame] | 484 | // Loop getting all the bytes in the argument |
| 485 | uArgument = 0; |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 486 | for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) { |
Laurence Lundblade | 4c0cf84 | 2019-01-12 03:25:44 -0800 | [diff] [blame] | 487 | // This shift and add gives the endian conversion |
| 488 | uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf); |
| 489 | } |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 490 | } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) { |
Laurence Lundblade | 4c0cf84 | 2019-01-12 03:25:44 -0800 | [diff] [blame] | 491 | // The reserved and thus-far unused additional info values |
| 492 | nReturn = QCBOR_ERR_UNSUPPORTED; |
| 493 | goto Done; |
| 494 | } else { |
| 495 | // Less than 24, additional info is argument or 31, an indefinite length |
| 496 | // No more bytes to get |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 497 | uArgument = (uint64_t)nAdditionalInfo; |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 498 | } |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 499 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 500 | if(UsefulInputBuf_GetError(pUInBuf)) { |
| 501 | nReturn = QCBOR_ERR_HIT_END; |
| 502 | goto Done; |
| 503 | } |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 504 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 505 | // All successful if we got here. |
| 506 | nReturn = QCBOR_SUCCESS; |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 507 | *pnMajorType = nTmpMajorType; |
Laurence Lundblade | 4c0cf84 | 2019-01-12 03:25:44 -0800 | [diff] [blame] | 508 | *puArgument = uArgument; |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 509 | *pnAdditionalInfo = nAdditionalInfo; |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 510 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 511 | Done: |
| 512 | return nReturn; |
| 513 | } |
| 514 | |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 515 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 516 | /* |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 517 | CBOR doesn't explicitly specify two's compliment for integers but all |
| 518 | CPUs use it these days and the test vectors in the RFC are so. All |
| 519 | integers in the CBOR structure are positive and the major type |
| 520 | indicates positive or negative. CBOR can express positive integers |
| 521 | up to 2^x - 1 where x is the number of bits and negative integers |
| 522 | down to 2^x. Note that negative numbers can be one more away from |
| 523 | zero than positive. Stdint, as far as I can tell, uses two's |
| 524 | compliment to represent negative integers. |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 525 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 526 | See http://www.unix.org/whitepapers/64bit.html for reasons int isn't |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 527 | used carefully here, and in particular why it isn't used in the interface. |
| 528 | Also see |
| 529 | https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers |
| 530 | |
| 531 | Int is used for values that need less than 16-bits and would be subject |
| 532 | to integer promotion and complaining by static analyzers. |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 533 | */ |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 534 | inline static QCBORError |
| 535 | DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem) |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 536 | { |
Laurence Lundblade | 30816f2 | 2018-11-10 13:40:22 +0700 | [diff] [blame] | 537 | QCBORError nReturn = QCBOR_SUCCESS; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 538 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 539 | if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) { |
| 540 | if (uNumber <= INT64_MAX) { |
| 541 | pDecodedItem->val.int64 = (int64_t)uNumber; |
| 542 | pDecodedItem->uDataType = QCBOR_TYPE_INT64; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 543 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 544 | } else { |
| 545 | pDecodedItem->val.uint64 = uNumber; |
| 546 | pDecodedItem->uDataType = QCBOR_TYPE_UINT64; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 547 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 548 | } |
| 549 | } else { |
| 550 | if(uNumber <= INT64_MAX) { |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 551 | // CBOR's representation of negative numbers lines up with the |
| 552 | // two-compliment representation. A negative integer has one |
| 553 | // more in range than a positive integer. INT64_MIN is |
| 554 | // equal to (-INT64_MAX) - 1. |
| 555 | pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1; |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 556 | pDecodedItem->uDataType = QCBOR_TYPE_INT64; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 557 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 558 | } else { |
| 559 | // C can't represent a negative integer in this range |
Laurence Lundblade | 21d1d81 | 2019-09-28 22:47:49 -1000 | [diff] [blame] | 560 | // so it is an error. |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 561 | nReturn = QCBOR_ERR_INT_OVERFLOW; |
| 562 | } |
| 563 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 564 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 565 | return nReturn; |
| 566 | } |
| 567 | |
| 568 | // Make sure #define value line up as DecodeSimple counts on this. |
| 569 | #if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE |
| 570 | #error QCBOR_TYPE_FALSE macro value wrong |
| 571 | #endif |
| 572 | |
| 573 | #if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE |
| 574 | #error QCBOR_TYPE_TRUE macro value wrong |
| 575 | #endif |
| 576 | |
| 577 | #if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL |
| 578 | #error QCBOR_TYPE_NULL macro value wrong |
| 579 | #endif |
| 580 | |
| 581 | #if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF |
| 582 | #error QCBOR_TYPE_UNDEF macro value wrong |
| 583 | #endif |
| 584 | |
Laurence Lundblade | 0f99d69 | 2018-09-26 14:39:28 -0700 | [diff] [blame] | 585 | #if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK |
| 586 | #error QCBOR_TYPE_BREAK macro value wrong |
| 587 | #endif |
| 588 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 589 | #if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT |
| 590 | #error QCBOR_TYPE_DOUBLE macro value wrong |
| 591 | #endif |
| 592 | |
| 593 | #if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT |
| 594 | #error QCBOR_TYPE_FLOAT macro value wrong |
| 595 | #endif |
| 596 | |
| 597 | /* |
| 598 | Decode true, false, floats, break... |
| 599 | */ |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 600 | inline static QCBORError |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 601 | DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem) |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 602 | { |
Laurence Lundblade | 30816f2 | 2018-11-10 13:40:22 +0700 | [diff] [blame] | 603 | QCBORError nReturn = QCBOR_SUCCESS; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 604 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 605 | // uAdditionalInfo is 5 bits from the initial byte compile time checks |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 606 | // above make sure uAdditionalInfo values line up with uDataType values. |
| 607 | // DecodeTypeAndNumber never returns a major type > 1f so cast is safe |
| 608 | pDecodedItem->uDataType = (uint8_t)nAdditionalInfo; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 609 | |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 610 | switch(nAdditionalInfo) { |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 611 | // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are |
| 612 | // caught before this is called. |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 613 | |
Laurence Lundblade | cc2ed34 | 2018-09-22 17:29:55 -0700 | [diff] [blame] | 614 | case HALF_PREC_FLOAT: |
Laurence Lundblade | 67bd551 | 2018-11-02 21:44:06 +0700 | [diff] [blame] | 615 | pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber); |
| 616 | pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE; |
Laurence Lundblade | 12d32c5 | 2018-09-19 11:25:27 -0700 | [diff] [blame] | 617 | break; |
Laurence Lundblade | cc2ed34 | 2018-09-22 17:29:55 -0700 | [diff] [blame] | 618 | case SINGLE_PREC_FLOAT: |
Laurence Lundblade | 67bd551 | 2018-11-02 21:44:06 +0700 | [diff] [blame] | 619 | pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber); |
| 620 | pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE; |
Laurence Lundblade | 12d32c5 | 2018-09-19 11:25:27 -0700 | [diff] [blame] | 621 | break; |
| 622 | case DOUBLE_PREC_FLOAT: |
| 623 | pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber); |
Laurence Lundblade | 67bd551 | 2018-11-02 21:44:06 +0700 | [diff] [blame] | 624 | pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE; |
Laurence Lundblade | 12d32c5 | 2018-09-19 11:25:27 -0700 | [diff] [blame] | 625 | break; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 626 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 627 | case CBOR_SIMPLEV_FALSE: // 20 |
| 628 | case CBOR_SIMPLEV_TRUE: // 21 |
| 629 | case CBOR_SIMPLEV_NULL: // 22 |
| 630 | case CBOR_SIMPLEV_UNDEF: // 23 |
Laurence Lundblade | 0f99d69 | 2018-09-26 14:39:28 -0700 | [diff] [blame] | 631 | case CBOR_SIMPLE_BREAK: // 31 |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 632 | break; // nothing to do |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 633 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 634 | case CBOR_SIMPLEV_ONEBYTE: // 24 |
| 635 | if(uNumber <= CBOR_SIMPLE_BREAK) { |
| 636 | // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7 |
Laurence Lundblade | 077475f | 2019-04-26 09:06:33 -0700 | [diff] [blame] | 637 | nReturn = QCBOR_ERR_BAD_TYPE_7; |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 638 | goto Done; |
| 639 | } |
Laurence Lundblade | 5e39082 | 2019-01-06 12:35:01 -0800 | [diff] [blame] | 640 | /* FALLTHROUGH */ |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 641 | // fall through intentionally |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 642 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 643 | default: // 0-19 |
| 644 | pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE; |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 645 | /* |
| 646 | DecodeTypeAndNumber will make uNumber equal to |
| 647 | uAdditionalInfo when uAdditionalInfo is < 24 This cast is |
| 648 | safe because the 2, 4 and 8 byte lengths of uNumber are in |
| 649 | the double/float cases above |
| 650 | */ |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 651 | pDecodedItem->val.uSimple = (uint8_t)uNumber; |
| 652 | break; |
| 653 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 654 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 655 | Done: |
| 656 | return nReturn; |
| 657 | } |
| 658 | |
| 659 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 660 | /* |
Laurence Lundblade | 471a3fd | 2018-10-18 21:27:45 +0530 | [diff] [blame] | 661 | Decode text and byte strings. Call the string allocator if asked to. |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 662 | */ |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 663 | inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator, |
| 664 | int nMajorType, |
| 665 | uint64_t uStrLen, |
| 666 | UsefulInputBuf *pUInBuf, |
| 667 | QCBORItem *pDecodedItem) |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 668 | { |
Laurence Lundblade | 30816f2 | 2018-11-10 13:40:22 +0700 | [diff] [blame] | 669 | QCBORError nReturn = QCBOR_SUCCESS; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 670 | |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 671 | // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs. |
| 672 | // This check makes the casts to size_t below safe. |
| 673 | |
| 674 | // 4 bytes less than the largest sizeof() so this can be tested by |
| 675 | // putting a SIZE_MAX length in the CBOR test input (no one will |
| 676 | // care the limit on strings is 4 bytes shorter). |
| 677 | if(uStrLen > SIZE_MAX-4) { |
| 678 | nReturn = QCBOR_ERR_STRING_TOO_LONG; |
| 679 | goto Done; |
| 680 | } |
| 681 | |
| 682 | const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen); |
Laurence Lundblade | 471a3fd | 2018-10-18 21:27:45 +0530 | [diff] [blame] | 683 | if(UsefulBuf_IsNULLC(Bytes)) { |
| 684 | // Failed to get the bytes for this string item |
| 685 | nReturn = QCBOR_ERR_HIT_END; |
| 686 | goto Done; |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 687 | } |
Laurence Lundblade | 471a3fd | 2018-10-18 21:27:45 +0530 | [diff] [blame] | 688 | |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 689 | if(pAllocator) { |
Laurence Lundblade | 471a3fd | 2018-10-18 21:27:45 +0530 | [diff] [blame] | 690 | // We are asked to use string allocator to make a copy |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 691 | UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen); |
Laurence Lundblade | 471a3fd | 2018-10-18 21:27:45 +0530 | [diff] [blame] | 692 | if(UsefulBuf_IsNULL(NewMem)) { |
Laurence Lundblade | 30816f2 | 2018-11-10 13:40:22 +0700 | [diff] [blame] | 693 | nReturn = QCBOR_ERR_STRING_ALLOCATE; |
Laurence Lundblade | 471a3fd | 2018-10-18 21:27:45 +0530 | [diff] [blame] | 694 | goto Done; |
| 695 | } |
| 696 | pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes); |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 697 | pDecodedItem->uDataAlloc = 1; |
Laurence Lundblade | 471a3fd | 2018-10-18 21:27:45 +0530 | [diff] [blame] | 698 | } else { |
| 699 | // Normal case with no string allocator |
| 700 | pDecodedItem->val.string = Bytes; |
| 701 | } |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 702 | const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING); |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 703 | // Cast because ternary operator causes promotion to integer |
| 704 | pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING |
| 705 | : QCBOR_TYPE_TEXT_STRING); |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 706 | |
Laurence Lundblade | 471a3fd | 2018-10-18 21:27:45 +0530 | [diff] [blame] | 707 | Done: |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 708 | return nReturn; |
| 709 | } |
| 710 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 711 | |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 712 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 713 | |
| 714 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 715 | |
| 716 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 717 | // Make sure the constants align as this is assumed by |
| 718 | // the GetAnItem() implementation |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 719 | #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY |
| 720 | #error QCBOR_TYPE_ARRAY value not lined up with major type |
| 721 | #endif |
| 722 | #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP |
| 723 | #error QCBOR_TYPE_MAP value not lined up with major type |
| 724 | #endif |
| 725 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 726 | /* |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 727 | This gets a single data item and decodes it including preceding |
| 728 | optional tagging. This does not deal with arrays and maps and nesting |
| 729 | except to decode the data item introducing them. Arrays and maps are |
| 730 | handled at the next level up in GetNext(). |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 731 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 732 | Errors detected here include: an array that is too long to decode, |
| 733 | hit end of buffer unexpectedly, a few forms of invalid encoded CBOR |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 734 | */ |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 735 | static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf, |
| 736 | QCBORItem *pDecodedItem, |
| 737 | const QCORInternalAllocator *pAllocator) |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 738 | { |
Laurence Lundblade | 30816f2 | 2018-11-10 13:40:22 +0700 | [diff] [blame] | 739 | QCBORError nReturn; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 740 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 741 | /* |
| 742 | Get the major type and the number. Number could be length of more |
| 743 | bytes or the value depending on the major type nAdditionalInfo is |
| 744 | an encoding of the length of the uNumber and is needed to decode |
| 745 | floats and doubles |
| 746 | */ |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 747 | int nMajorType; |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 748 | uint64_t uNumber; |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 749 | int nAdditionalInfo; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 750 | |
Laurence Lundblade | 4b09f63 | 2019-10-09 14:34:59 -0700 | [diff] [blame] | 751 | memset(pDecodedItem, 0, sizeof(QCBORItem)); |
| 752 | |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 753 | nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo); |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 754 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 755 | // Error out here if we got into trouble on the type and number. The |
| 756 | // code after this will not work if the type and number is not good. |
Laurence Lundblade | 3a6042e | 2019-06-28 19:58:04 -0700 | [diff] [blame] | 757 | if(nReturn) { |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 758 | goto Done; |
Laurence Lundblade | 3a6042e | 2019-06-28 19:58:04 -0700 | [diff] [blame] | 759 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 760 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 761 | // At this point the major type and the value are valid. We've got |
| 762 | // the type and the number that starts every CBOR data item. |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 763 | switch (nMajorType) { |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 764 | case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0 |
| 765 | case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1 |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 766 | if(nAdditionalInfo == LEN_IS_INDEFINITE) { |
Laurence Lundblade | 3a6042e | 2019-06-28 19:58:04 -0700 | [diff] [blame] | 767 | nReturn = QCBOR_ERR_BAD_INT; |
| 768 | } else { |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 769 | nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem); |
Laurence Lundblade | 3a6042e | 2019-06-28 19:58:04 -0700 | [diff] [blame] | 770 | } |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 771 | break; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 772 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 773 | case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2 |
| 774 | case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3 |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 775 | if(nAdditionalInfo == LEN_IS_INDEFINITE) { |
| 776 | const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING); |
| 777 | pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING |
| 778 | : QCBOR_TYPE_TEXT_STRING); |
Laurence Lundblade | a44d506 | 2018-10-17 18:45:12 +0530 | [diff] [blame] | 779 | pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX}; |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 780 | } else { |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 781 | nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem); |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 782 | } |
| 783 | break; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 784 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 785 | case CBOR_MAJOR_TYPE_ARRAY: // Major type 4 |
| 786 | case CBOR_MAJOR_TYPE_MAP: // Major type 5 |
| 787 | // Record the number of items in the array or map |
| 788 | if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) { |
| 789 | nReturn = QCBOR_ERR_ARRAY_TOO_LONG; |
| 790 | goto Done; |
| 791 | } |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 792 | if(nAdditionalInfo == LEN_IS_INDEFINITE) { |
Laurence Lundblade | a44d506 | 2018-10-17 18:45:12 +0530 | [diff] [blame] | 793 | pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 794 | } else { |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 795 | // type conversion OK because of check above |
| 796 | pDecodedItem->val.uCount = (uint16_t)uNumber; |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 797 | } |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 798 | // C preproc #if above makes sure constants for major types align |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 799 | // DecodeTypeAndNumber never returns a major type > 7 so cast is safe |
| 800 | pDecodedItem->uDataType = (uint8_t)nMajorType; |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 801 | break; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 802 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 803 | case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 804 | if(nAdditionalInfo == LEN_IS_INDEFINITE) { |
Laurence Lundblade | bb1062e | 2019-08-12 23:28:54 -0700 | [diff] [blame] | 805 | nReturn = QCBOR_ERR_BAD_INT; |
| 806 | } else { |
| 807 | pDecodedItem->val.uTagV = uNumber; |
| 808 | pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG; |
| 809 | } |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 810 | break; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 811 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 812 | case CBOR_MAJOR_TYPE_SIMPLE: |
| 813 | // Major type 7, float, double, true, false, null... |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 814 | nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem); |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 815 | break; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 816 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 817 | default: |
| 818 | // Never happens because DecodeTypeAndNumber() should never return > 7 |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 819 | nReturn = QCBOR_ERR_UNSUPPORTED; |
| 820 | break; |
| 821 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 822 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 823 | Done: |
| 824 | return nReturn; |
| 825 | } |
| 826 | |
| 827 | |
| 828 | |
| 829 | /* |
Laurence Lundblade | 20b533d | 2018-10-08 20:44:53 +0800 | [diff] [blame] | 830 | This layer deals with indefinite length strings. It pulls all the |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 831 | individual chunk items together into one QCBORItem using the string |
| 832 | allocator. |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 833 | |
Laurence Lundblade | 7e0d13b | 2018-10-16 19:54:13 +0530 | [diff] [blame] | 834 | Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 835 | */ |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 836 | static inline QCBORError |
| 837 | GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem) |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 838 | { |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 839 | // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96 |
Laurence Lundblade | d6dfe6d | 2020-04-09 10:21:36 -0700 | [diff] [blame] | 840 | |
| 841 | // Get pointer to string allocator. First use is to pass it to |
| 842 | // GetNext_Item() when option is set to allocate for *every* string. |
| 843 | // Second use here is to allocate space to coallese indefinite |
| 844 | // length string items into one. |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 845 | const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ? |
| 846 | &(me->StringAllocator) : |
| 847 | NULL; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 848 | |
Laurence Lundblade | d6dfe6d | 2020-04-09 10:21:36 -0700 | [diff] [blame] | 849 | QCBORError nReturn; |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 850 | nReturn = GetNext_Item(&(me->InBuf), |
| 851 | pDecodedItem, |
| 852 | me->bStringAllocateAll ? pAllocator: NULL); |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 853 | if(nReturn) { |
| 854 | goto Done; |
| 855 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 856 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 857 | // To reduce code size by removing support for indefinite length strings, the |
Laurence Lundblade | 7e0d13b | 2018-10-16 19:54:13 +0530 | [diff] [blame] | 858 | // code in this function from here down can be eliminated. Run tests, except |
| 859 | // indefinite length string tests, to be sure all is OK if this is removed. |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 860 | |
Laurence Lundblade | 20b533d | 2018-10-08 20:44:53 +0800 | [diff] [blame] | 861 | // Only do indefinite length processing on strings |
Laurence Lundblade | d6dfe6d | 2020-04-09 10:21:36 -0700 | [diff] [blame] | 862 | const uint8_t uStringType = pDecodedItem->uDataType; |
| 863 | if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) { |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 864 | goto Done; // no need to do any work here on non-string types |
| 865 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 866 | |
Laurence Lundblade | 20b533d | 2018-10-08 20:44:53 +0800 | [diff] [blame] | 867 | // Is this a string with an indefinite length? |
Laurence Lundblade | 7e0d13b | 2018-10-16 19:54:13 +0530 | [diff] [blame] | 868 | if(pDecodedItem->val.string.len != SIZE_MAX) { |
Laurence Lundblade | 20b533d | 2018-10-08 20:44:53 +0800 | [diff] [blame] | 869 | goto Done; // length is not indefinite, so no work to do here |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 870 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 871 | |
Laurence Lundblade | 7e0d13b | 2018-10-16 19:54:13 +0530 | [diff] [blame] | 872 | // Can't do indefinite length strings without a string allocator |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 873 | if(pAllocator == NULL) { |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 874 | nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR; |
| 875 | goto Done; |
| 876 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 877 | |
Laurence Lundblade | 2a6850e | 2018-10-28 20:13:44 +0700 | [diff] [blame] | 878 | // Loop getting chunk of indefinite string |
Laurence Lundblade | d6dfe6d | 2020-04-09 10:21:36 -0700 | [diff] [blame] | 879 | UsefulBufC FullString = NULLUsefulBufC; |
| 880 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 881 | for(;;) { |
Laurence Lundblade | 2a6850e | 2018-10-28 20:13:44 +0700 | [diff] [blame] | 882 | // Get item for next chunk |
| 883 | QCBORItem StringChunkItem; |
Laurence Lundblade | d6dfe6d | 2020-04-09 10:21:36 -0700 | [diff] [blame] | 884 | // NULL string allocator passed here. Do not need to allocate |
| 885 | // chunks even if bStringAllocateAll is set. |
Laurence Lundblade | fae26bf | 2019-02-18 11:15:43 -0800 | [diff] [blame] | 886 | nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL); |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 887 | if(nReturn) { |
Laurence Lundblade | 2a6850e | 2018-10-28 20:13:44 +0700 | [diff] [blame] | 888 | break; // Error getting the next chunk |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 889 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 890 | |
Laurence Lundblade | 7e0d13b | 2018-10-16 19:54:13 +0530 | [diff] [blame] | 891 | // See if it is a marker at end of indefinite length string |
Laurence Lundblade | 2a6850e | 2018-10-28 20:13:44 +0700 | [diff] [blame] | 892 | if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) { |
Laurence Lundblade | 20b533d | 2018-10-08 20:44:53 +0800 | [diff] [blame] | 893 | // String is complete |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 894 | pDecodedItem->val.string = FullString; |
Laurence Lundblade | 57dd144 | 2018-10-15 20:26:28 +0530 | [diff] [blame] | 895 | pDecodedItem->uDataAlloc = 1; |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 896 | break; |
| 897 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 898 | |
Laurence Lundblade | 2a6850e | 2018-10-28 20:13:44 +0700 | [diff] [blame] | 899 | // Match data type of chunk to type at beginning. |
Laurence Lundblade | 7e0d13b | 2018-10-16 19:54:13 +0530 | [diff] [blame] | 900 | // Also catches error of other non-string types that don't belong. |
Laurence Lundblade | bb1062e | 2019-08-12 23:28:54 -0700 | [diff] [blame] | 901 | // Also catches indefinite length strings inside indefinite length strings |
Laurence Lundblade | c5fef68 | 2020-01-25 11:38:45 -0800 | [diff] [blame] | 902 | if(StringChunkItem.uDataType != uStringType || |
| 903 | StringChunkItem.val.string.len == SIZE_MAX) { |
Laurence Lundblade | 30816f2 | 2018-11-10 13:40:22 +0700 | [diff] [blame] | 904 | nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK; |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 905 | break; |
| 906 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 907 | |
Laurence Lundblade | 471a3fd | 2018-10-18 21:27:45 +0530 | [diff] [blame] | 908 | // Alloc new buffer or expand previously allocated buffer so it can fit |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 909 | // The first time throurgh FullString.ptr is NULL and this is |
| 910 | // equivalent to StringAllocator_Allocate() |
| 911 | UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator, |
| 912 | UNCONST_POINTER(FullString.ptr), |
| 913 | FullString.len + StringChunkItem.val.string.len); |
| 914 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 915 | if(UsefulBuf_IsNULL(NewMem)) { |
Laurence Lundblade | 7e0d13b | 2018-10-16 19:54:13 +0530 | [diff] [blame] | 916 | // Allocation of memory for the string failed |
Laurence Lundblade | 30816f2 | 2018-11-10 13:40:22 +0700 | [diff] [blame] | 917 | nReturn = QCBOR_ERR_STRING_ALLOCATE; |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 918 | break; |
| 919 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 920 | |
Laurence Lundblade | 2a6850e | 2018-10-28 20:13:44 +0700 | [diff] [blame] | 921 | // Copy new string chunk at the end of string so far. |
| 922 | FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string); |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 923 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 924 | |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 925 | if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) { |
| 926 | // Getting the item failed, clean up the allocated memory |
| 927 | StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr)); |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 928 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 929 | |
Laurence Lundblade | d6dfe6d | 2020-04-09 10:21:36 -0700 | [diff] [blame] | 930 | Done: |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 931 | return nReturn; |
| 932 | } |
| 933 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 934 | |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 935 | uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) { |
| 936 | if(uTagVal < 0xfff0) { |
| 937 | return uTagVal; |
| 938 | } else { |
| 939 | // TODO constant and error check |
| 940 | int x = uTagVal - 0xfff0; |
| 941 | return me->auMappedTags[x]; |
| 942 | } |
| 943 | } |
| 944 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 945 | /* |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 946 | Gets all optional tag data items preceding a data item that is not an |
| 947 | optional tag and records them as bits in the tag map. |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 948 | */ |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 949 | static QCBORError |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 950 | GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem) |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 951 | { |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 952 | // Stack usage: int/ptr: 3 -- 24 |
Laurence Lundblade | 30816f2 | 2018-11-10 13:40:22 +0700 | [diff] [blame] | 953 | QCBORError nReturn; |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 954 | |
Laurence Lundblade | c75e68b | 2020-06-15 20:34:46 -0700 | [diff] [blame] | 955 | uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16, |
| 956 | CBOR_TAG_INVALID16, |
| 957 | CBOR_TAG_INVALID16, |
| 958 | CBOR_TAG_INVALID16}; |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 959 | |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 960 | // Loop fetching items until the item fetched is not a tag |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 961 | for(;;) { |
| 962 | nReturn = GetNext_FullItem(me, pDecodedItem); |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 963 | if(nReturn) { |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 964 | goto Done; // Error out of the loop |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 965 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 966 | |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 967 | if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) { |
| 968 | // Successful exit from loop; maybe got some tags, maybe not |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 969 | memcpy(pDecodedItem->uTags, auTags, sizeof(auTags)); |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 970 | break; |
| 971 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 972 | |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 973 | // Is there room for the tag in the tags list? |
| 974 | size_t uTagIndex; |
| 975 | for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) { |
Laurence Lundblade | c75e68b | 2020-06-15 20:34:46 -0700 | [diff] [blame] | 976 | if(auTags[uTagIndex] == CBOR_TAG_INVALID16) { |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 977 | break; |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 978 | } |
| 979 | } |
| 980 | if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) { |
Laurence Lundblade | c75e68b | 2020-06-15 20:34:46 -0700 | [diff] [blame] | 981 | return QCBOR_ERR_TOO_MANY_TAGS; |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 982 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 983 | |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 984 | // Is the tag > 16 bits? |
Laurence Lundblade | c75e68b | 2020-06-15 20:34:46 -0700 | [diff] [blame] | 985 | if(pDecodedItem->val.uTagV > CBOR_TAG_INVALID16) { |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 986 | size_t uTagMapIndex; |
| 987 | // Is there room in the tag map? |
| 988 | for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) { |
Laurence Lundblade | c75e68b | 2020-06-15 20:34:46 -0700 | [diff] [blame] | 989 | if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) { |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 990 | break; |
| 991 | } |
| 992 | if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) { |
| 993 | break; |
| 994 | } |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 995 | } |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 996 | if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) { |
| 997 | // No room for the tag |
| 998 | return 97; // TODO error code |
| 999 | } |
| 1000 | |
| 1001 | // Cover the case where tag is new and were it is already in the map |
| 1002 | me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV; |
| 1003 | auTags[uTagIndex] = (uint16_t)(uTagMapIndex + 0xfff0); // TODO proper constant and cast |
| 1004 | |
| 1005 | } else { |
| 1006 | auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV; |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 1007 | } |
| 1008 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1009 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1010 | Done: |
| 1011 | return nReturn; |
| 1012 | } |
| 1013 | |
| 1014 | |
| 1015 | /* |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1016 | This layer takes care of map entries. It combines the label and data |
| 1017 | items into one QCBORItem. |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1018 | */ |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1019 | static inline QCBORError |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1020 | GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem) |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1021 | { |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 1022 | // Stack use: int/ptr 1, QCBORItem -- 56 |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1023 | QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem); |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1024 | if(nReturn) |
| 1025 | goto Done; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1026 | |
Laurence Lundblade | 742df4a | 2018-10-13 20:07:17 +0800 | [diff] [blame] | 1027 | if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) { |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 1028 | // Break can't be a map entry |
Laurence Lundblade | 742df4a | 2018-10-13 20:07:17 +0800 | [diff] [blame] | 1029 | goto Done; |
| 1030 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1031 | |
Laurence Lundblade | d61cbf3 | 2018-12-09 11:42:21 -0800 | [diff] [blame] | 1032 | if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) { |
| 1033 | // In a map and caller wants maps decoded, not treated as arrays |
| 1034 | |
| 1035 | if(DecodeNesting_TypeIsMap(&(me->nesting))) { |
| 1036 | // If in a map and the right decoding mode, get the label |
| 1037 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1038 | // Save label in pDecodedItem and get the next which will |
| 1039 | // be the real data |
Laurence Lundblade | ccfb8cd | 2018-12-07 21:11:30 +0900 | [diff] [blame] | 1040 | QCBORItem LabelItem = *pDecodedItem; |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1041 | nReturn = GetNext_TaggedItem(me, pDecodedItem); |
Laurence Lundblade | ccfb8cd | 2018-12-07 21:11:30 +0900 | [diff] [blame] | 1042 | if(nReturn) |
| 1043 | goto Done; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1044 | |
Laurence Lundblade | 57dd144 | 2018-10-15 20:26:28 +0530 | [diff] [blame] | 1045 | pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc; |
Laurence Lundblade | ccfb8cd | 2018-12-07 21:11:30 +0900 | [diff] [blame] | 1046 | |
| 1047 | if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) { |
| 1048 | // strings are always good labels |
| 1049 | pDecodedItem->label.string = LabelItem.val.string; |
| 1050 | pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING; |
| 1051 | } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) { |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1052 | // It's not a string and we only want strings |
Laurence Lundblade | ccfb8cd | 2018-12-07 21:11:30 +0900 | [diff] [blame] | 1053 | nReturn = QCBOR_ERR_MAP_LABEL_TYPE; |
| 1054 | goto Done; |
| 1055 | } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) { |
| 1056 | pDecodedItem->label.int64 = LabelItem.val.int64; |
| 1057 | pDecodedItem->uLabelType = QCBOR_TYPE_INT64; |
| 1058 | } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) { |
| 1059 | pDecodedItem->label.uint64 = LabelItem.val.uint64; |
| 1060 | pDecodedItem->uLabelType = QCBOR_TYPE_UINT64; |
| 1061 | } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) { |
| 1062 | pDecodedItem->label.string = LabelItem.val.string; |
| 1063 | pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc; |
| 1064 | pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING; |
| 1065 | } else { |
| 1066 | // label is not an int or a string. It is an arrray |
| 1067 | // or a float or such and this implementation doesn't handle that. |
| 1068 | // Also, tags on labels are ignored. |
| 1069 | nReturn = QCBOR_ERR_MAP_LABEL_TYPE; |
| 1070 | goto Done; |
| 1071 | } |
Laurence Lundblade | d61cbf3 | 2018-12-09 11:42:21 -0800 | [diff] [blame] | 1072 | } |
| 1073 | } else { |
| 1074 | if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) { |
Laurence Lundblade | e6bcef1 | 2020-04-01 10:56:27 -0700 | [diff] [blame] | 1075 | if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) { |
| 1076 | nReturn = QCBOR_ERR_ARRAY_TOO_LONG; |
| 1077 | goto Done; |
| 1078 | } |
Laurence Lundblade | d61cbf3 | 2018-12-09 11:42:21 -0800 | [diff] [blame] | 1079 | // Decoding a map as an array |
| 1080 | pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY; |
Laurence Lundblade | e6bcef1 | 2020-04-01 10:56:27 -0700 | [diff] [blame] | 1081 | // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2 |
| 1082 | // Cast is needed because of integer promotion |
| 1083 | pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2); |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1084 | } |
| 1085 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1086 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 1087 | Done: |
| 1088 | return nReturn; |
| 1089 | } |
| 1090 | |
| 1091 | |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1092 | static QCBORError |
| 1093 | NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak) |
| 1094 | { |
| 1095 | *pbNextIsBreak = false; |
| 1096 | if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) { |
| 1097 | // TODO: use the Peek method? |
| 1098 | QCBORItem Peek; |
| 1099 | size_t uPeek = UsefulInputBuf_Tell(pUIB); |
| 1100 | QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL); |
| 1101 | if(uReturn != QCBOR_SUCCESS) { |
| 1102 | return uReturn; |
| 1103 | } |
| 1104 | if(Peek.uDataType != QCBOR_TYPE_BREAK) { |
| 1105 | // It is not a break, rewind so it can be processed normally. |
| 1106 | UsefulInputBuf_Seek(pUIB, uPeek); |
| 1107 | } else { |
| 1108 | *pbNextIsBreak = true; |
| 1109 | } |
| 1110 | } |
| 1111 | |
| 1112 | return QCBOR_SUCCESS; |
| 1113 | } |
| 1114 | |
| 1115 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 1116 | /* |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 1117 | An item was just consumed, now figure out if it was the |
| 1118 | end of an array or map that can be closed out. That |
| 1119 | may in turn close out another map or array. |
| 1120 | */ |
| 1121 | static QCBORError Ascender(QCBORDecodeContext *pMe) |
| 1122 | { |
| 1123 | QCBORError uReturn; |
| 1124 | |
| 1125 | /* This loops ascending nesting levels as long as there is ascending to do */ |
| 1126 | while(1) { |
| 1127 | if(!DecodeNesting_IsAtTop(&(pMe->nesting)) && !DecodeNesting_IsIndefiniteLength(&(pMe->nesting))) { |
| 1128 | /* 1st Case: in a definite length array (not a CBOR sequence). Simply |
| 1129 | decrement the item count. If it doesn't go to zero, then all is done. |
| 1130 | If it does go to zero, the bottom of the loop ascends one nesting level |
| 1131 | and the loop continues. |
| 1132 | */ |
| 1133 | DecodeNesting_DecrementX(&(pMe->nesting)); |
| 1134 | if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) { |
| 1135 | /* Didn't close out map or array; all work here is done */ |
| 1136 | break; |
| 1137 | } |
| 1138 | |
| 1139 | } else { |
| 1140 | /* 2nd, 3rd, 4th and 5th cases where a check for a following CBOR break must be checked for */ |
| 1141 | bool bIsBreak = false; |
| 1142 | uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak); |
| 1143 | if(uReturn != QCBOR_SUCCESS) { |
| 1144 | goto Done; |
| 1145 | } |
| 1146 | |
| 1147 | if(bIsBreak) { |
| 1148 | if(DecodeNesting_IsAtTop(&(pMe->nesting))) { |
| 1149 | /* 2nd case where a break occurs at the top level and thus |
| 1150 | in a CBOR sequence. Always an error because break is |
| 1151 | not inside an indefinite length map or array. */ |
| 1152 | uReturn = QCBOR_ERR_BAD_BREAK; |
| 1153 | goto Done; |
| 1154 | } else { |
| 1155 | /* 3rd case, the normal end of an indefinite length map |
| 1156 | or array. The bottom of the loop ascends one nesting |
| 1157 | level and the loop continues. */ |
| 1158 | } |
| 1159 | } else { |
| 1160 | /* 4th case where an indefinite length array is not closed out |
| 1161 | and 5th case which is just an item in a CBOR sequence. In either |
| 1162 | there is no close out so all work here is done. |
| 1163 | */ |
| 1164 | break; |
| 1165 | } |
| 1166 | } |
| 1167 | |
| 1168 | /* All items in the level have been consumed. */ |
| 1169 | |
| 1170 | /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */ |
| 1171 | if(DecodeNesting_InBoundedMode(&(pMe->nesting))) { |
| 1172 | /* Set the count to zero for indefinite length arrays to indicate cursor is at end of bounded map / array */ |
| 1173 | pMe->nesting.pCurrent->uCount = 0; |
| 1174 | break; |
| 1175 | } |
| 1176 | |
| 1177 | /* Finally, actually ascend one level. */ |
| 1178 | DecodeNesting_Ascend(&(pMe->nesting)); |
| 1179 | } |
| 1180 | |
| 1181 | uReturn = QCBOR_SUCCESS; |
| 1182 | |
| 1183 | Done: |
| 1184 | return uReturn; |
| 1185 | } |
| 1186 | |
| 1187 | |
| 1188 | /* |
Laurence Lundblade | 844bb5c | 2020-03-01 17:27:25 -0800 | [diff] [blame] | 1189 | Public function, see header qcbor/qcbor_decode.h file |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 1190 | TODO: correct this comment |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 1191 | */ |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1192 | static QCBORError |
| 1193 | QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem) |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 1194 | { |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1195 | QCBORError uReturn; |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 1196 | /* === First figure out if at the end of traversal === */ |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1197 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 1198 | /* Case 1. Out of bytes to consume. |
| 1199 | |
| 1200 | This is either the end of the top-level CBOR that was give |
| 1201 | to QCBORDecode_Init() or the end of a tag 24 bstr wrapped CBOR. |
| 1202 | It is detected by all bytes being consumed from the UsefulInputBuf. |
| 1203 | |
| 1204 | To go back out of the tag 24 bstr wrapped item, the caller must |
| 1205 | explicitly call Exit() which will reset the UsefulInputBuf |
| 1206 | to the next highest bstr wrapped or the top level. |
| 1207 | |
| 1208 | This is always the end condition that QCBORDecode_Finish() |
| 1209 | considers complete. |
| 1210 | |
| 1211 | TODO: can the DecodeNesting_IsAtTop be removed? QCBORDecode_Finish() |
| 1212 | will perform this check. |
| 1213 | |
| 1214 | */ |
Laurence Lundblade | 937ea81 | 2020-05-08 11:38:23 -0700 | [diff] [blame] | 1215 | /* For a pre-order traversal a non-error end occurs when there |
| 1216 | are no more bytes to consume and the nesting level is at the top. |
| 1217 | If it's not at the top, then the CBOR is not well formed. This error |
| 1218 | is caught elsewhere. |
| 1219 | |
| 1220 | This handles the end of CBOR sequences as well as non-sequences. */ |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 1221 | if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && DecodeNesting_IsAtTop(&(me->nesting))) { |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1222 | uReturn = QCBOR_ERR_NO_MORE_ITEMS; |
Laurence Lundblade | bb1062e | 2019-08-12 23:28:54 -0700 | [diff] [blame] | 1223 | goto Done; |
| 1224 | } |
Laurence Lundblade | 937ea81 | 2020-05-08 11:38:23 -0700 | [diff] [blame] | 1225 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 1226 | |
| 1227 | /* Case 2. End of map or array in bounded mode |
| 1228 | |
| 1229 | The caller is attempting traveral of a bounded map or array and |
| 1230 | has got to the end of it. |
| 1231 | |
| 1232 | The caller must explicitly exit the bounded mode map or array |
| 1233 | to get past this condition. |
| 1234 | |
| 1235 | To complete a decode of the full input CBOR, the caller must |
| 1236 | exit all maps and arrays in bounded mode and this is never |
| 1237 | the successful end of decoding. |
| 1238 | |
| 1239 | */ |
Laurence Lundblade | 64b607e | 2020-05-13 13:05:57 -0700 | [diff] [blame] | 1240 | /* It is also an end of the input when in map mode and the cursor |
Laurence Lundblade | 937ea81 | 2020-05-08 11:38:23 -0700 | [diff] [blame] | 1241 | is at the end of the map */ |
| 1242 | |
| 1243 | |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1244 | // This is to handle bounded mode |
Laurence Lundblade | 937ea81 | 2020-05-08 11:38:23 -0700 | [diff] [blame] | 1245 | if(DecodeNesting_AtEnd(&(me->nesting))) { |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1246 | uReturn = QCBOR_ERR_NO_MORE_ITEMS; |
Laurence Lundblade | 3f9ef04 | 2020-04-14 13:15:51 -0700 | [diff] [blame] | 1247 | goto Done; |
| 1248 | } |
Laurence Lundblade | bb1062e | 2019-08-12 23:28:54 -0700 | [diff] [blame] | 1249 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 1250 | /* === Not at the end; get another item === */ |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1251 | uReturn = GetNext_MapEntry(me, pDecodedItem); |
| 1252 | if(uReturn) { |
Laurence Lundblade | 20b533d | 2018-10-08 20:44:53 +0800 | [diff] [blame] | 1253 | goto Done; |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 1254 | } |
Laurence Lundblade | 7e0d13b | 2018-10-16 19:54:13 +0530 | [diff] [blame] | 1255 | |
Laurence Lundblade | 64b607e | 2020-05-13 13:05:57 -0700 | [diff] [blame] | 1256 | // Breaks ending arrays/maps are always processed at the end of this function. |
Laurence Lundblade | 7e0d13b | 2018-10-16 19:54:13 +0530 | [diff] [blame] | 1257 | // They should never show up here. |
Laurence Lundblade | 6de3706 | 2018-10-15 12:22:42 +0530 | [diff] [blame] | 1258 | if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) { |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1259 | uReturn = QCBOR_ERR_BAD_BREAK; |
Laurence Lundblade | 6de3706 | 2018-10-15 12:22:42 +0530 | [diff] [blame] | 1260 | goto Done; |
Laurence Lundblade | 5b8c585 | 2018-10-14 21:11:42 +0530 | [diff] [blame] | 1261 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1262 | |
Laurence Lundblade | 6de3706 | 2018-10-15 12:22:42 +0530 | [diff] [blame] | 1263 | // Record the nesting level for this data item before processing any of |
Laurence Lundblade | 7e0d13b | 2018-10-16 19:54:13 +0530 | [diff] [blame] | 1264 | // decrementing and descending. |
Laurence Lundblade | 6de3706 | 2018-10-15 12:22:42 +0530 | [diff] [blame] | 1265 | pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting)); |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1266 | |
Laurence Lundblade | 6de3706 | 2018-10-15 12:22:42 +0530 | [diff] [blame] | 1267 | // Process the item just received for descent or decrement, and |
Laurence Lundblade | 64b607e | 2020-05-13 13:05:57 -0700 | [diff] [blame] | 1268 | // ascend if decrements are enough to close out a definite length array/map |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 1269 | if(IsMapOrArray(pDecodedItem->uDataType) && pDecodedItem->val.uCount != 0) { |
Laurence Lundblade | 9e3651c | 2018-10-10 11:49:55 +0800 | [diff] [blame] | 1270 | // If the new item is array or map, the nesting level descends |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1271 | uReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem->uDataType, pDecodedItem->val.uCount, 0L); |
Laurence Lundblade | 9e3651c | 2018-10-10 11:49:55 +0800 | [diff] [blame] | 1272 | // Maps and arrays do count in as items in the map/array that encloses |
| 1273 | // them so a decrement needs to be done for them too, but that is done |
| 1274 | // only when all the items in them have been processed, not when they |
Laurence Lundblade | 9916b1b | 2019-09-07 22:33:25 -0700 | [diff] [blame] | 1275 | // are opened with the exception of an empty map or array. |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1276 | if(uReturn != QCBOR_SUCCESS) { |
| 1277 | goto Done; |
| 1278 | } |
Laurence Lundblade | 5e87da6 | 2020-06-07 03:24:28 -0700 | [diff] [blame] | 1279 | } |
| 1280 | |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1281 | if(!IsMapOrArray(pDecodedItem->uDataType) || |
| 1282 | pDecodedItem->val.uCount == 0 || pDecodedItem->val.uCount == UINT16_MAX) { |
| 1283 | /* The following cases are handled here: |
| 1284 | - A non-aggregate like an integer or string |
| 1285 | - An empty definite length map or array |
| 1286 | - An indefinite length map or array that might be empty or might not. |
| 1287 | */ |
| 1288 | |
Laurence Lundblade | 5e87da6 | 2020-06-07 03:24:28 -0700 | [diff] [blame] | 1289 | |
| 1290 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 1291 | /* === Figure out if item got closed out maps or arrays === */ |
| 1292 | |
Laurence Lundblade | 5e87da6 | 2020-06-07 03:24:28 -0700 | [diff] [blame] | 1293 | /* |
| 1294 | This needs to decrement, check for end and ascend |
| 1295 | the tree until an an ascend is not possible or the bounded |
| 1296 | limit is reached or the end of the encoded CBOR input |
| 1297 | is reached. For |
| 1298 | definite length maps and arrays the end is by count. For |
| 1299 | indefinite it is by a break. |
| 1300 | |
| 1301 | Also state needs to be set that can tell the code at the |
| 1302 | beginning of this function that the end was reached. |
| 1303 | |
| 1304 | This is complicated... |
| 1305 | |
| 1306 | |
| 1307 | This will handle an indefinite length array |
| 1308 | inside a definte length array inside an indefinite |
| 1309 | length array... |
| 1310 | |
| 1311 | */ |
| 1312 | |
Laurence Lundblade | 9e3651c | 2018-10-10 11:49:55 +0800 | [diff] [blame] | 1313 | // Decrement the count of items in the enclosing map/array |
| 1314 | // If the count in the enclosing map/array goes to zero, that |
Laurence Lundblade | 6de3706 | 2018-10-15 12:22:42 +0530 | [diff] [blame] | 1315 | // triggers a decrement in the map/array above that and |
| 1316 | // an ascend in nesting level. |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1317 | /* If the just consumed item is at the end of a map or |
| 1318 | array ascend in the nesting tracking. That may |
| 1319 | in turn may be the end of the above nesting level |
| 1320 | and so on up to the end of the whole encoded CBOR. |
| 1321 | |
| 1322 | Each level could be a definite or indefinte length |
| 1323 | map or array. These are handled very differently. |
| 1324 | |
| 1325 | */ |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 1326 | uReturn = Ascender(me); |
| 1327 | if(uReturn) { |
| 1328 | goto Done; |
Laurence Lundblade | 5e87da6 | 2020-06-07 03:24:28 -0700 | [diff] [blame] | 1329 | } |
Laurence Lundblade | 6de3706 | 2018-10-15 12:22:42 +0530 | [diff] [blame] | 1330 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1331 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 1332 | |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1333 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 1334 | /* === Tell the caller the nest level of the next item === */ |
| 1335 | |
Laurence Lundblade | 6de3706 | 2018-10-15 12:22:42 +0530 | [diff] [blame] | 1336 | // Tell the caller what level is next. This tells them what maps/arrays |
| 1337 | // were closed out and makes it possible for them to reconstruct |
| 1338 | // the tree with just the information returned by GetNext |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 1339 | // TODO: pull this into DecodeNesting_GetLevel |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1340 | if(DecodeNesting_InBoundedMode(&(me->nesting)) && me->nesting.pCurrent->uCount == 0) { |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 1341 | // At end of a map / array in map mode, so next nest is 0 to |
| 1342 | // indicate this end. |
| 1343 | pDecodedItem->uNextNestLevel = 0; |
| 1344 | } else { |
| 1345 | pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting)); |
| 1346 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1347 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1348 | Done: |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1349 | if(uReturn != QCBOR_SUCCESS) { |
Laurence Lundblade | e9482dd | 2019-10-11 12:58:46 -0700 | [diff] [blame] | 1350 | // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE |
| 1351 | memset(pDecodedItem, 0, sizeof(QCBORItem)); |
| 1352 | } |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1353 | return uReturn; |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1354 | } |
| 1355 | |
| 1356 | |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1357 | /* |
| 1358 | Mostly just assign the right data type for the date string. |
| 1359 | */ |
| 1360 | inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem) |
| 1361 | { |
| 1362 | // Stack Use: UsefulBuf 1 16 |
| 1363 | if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) { |
| 1364 | return QCBOR_ERR_BAD_OPT_TAG; |
| 1365 | } |
| 1366 | |
| 1367 | const UsefulBufC Temp = pDecodedItem->val.string; |
| 1368 | pDecodedItem->val.dateString = Temp; |
| 1369 | pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING; |
| 1370 | return QCBOR_SUCCESS; |
| 1371 | } |
| 1372 | |
| 1373 | |
| 1374 | /* |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1375 | The epoch formatted date. Turns lots of different forms of encoding |
| 1376 | date into uniform one |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1377 | */ |
Laurence Lundblade | 06350ea | 2020-01-27 19:32:40 -0800 | [diff] [blame] | 1378 | static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem) |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1379 | { |
| 1380 | // Stack usage: 1 |
| 1381 | QCBORError nReturn = QCBOR_SUCCESS; |
| 1382 | |
| 1383 | pDecodedItem->val.epochDate.fSecondsFraction = 0; |
| 1384 | |
| 1385 | switch (pDecodedItem->uDataType) { |
| 1386 | |
| 1387 | case QCBOR_TYPE_INT64: |
| 1388 | pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64; |
| 1389 | break; |
| 1390 | |
| 1391 | case QCBOR_TYPE_UINT64: |
| 1392 | if(pDecodedItem->val.uint64 > INT64_MAX) { |
| 1393 | nReturn = QCBOR_ERR_DATE_OVERFLOW; |
| 1394 | goto Done; |
| 1395 | } |
Laurence Lundblade | 06350ea | 2020-01-27 19:32:40 -0800 | [diff] [blame] | 1396 | pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64; |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1397 | break; |
| 1398 | |
| 1399 | case QCBOR_TYPE_DOUBLE: |
| 1400 | { |
| 1401 | // This comparison needs to be done as a float before |
| 1402 | // conversion to an int64_t to be able to detect doubles |
| 1403 | // that are too large to fit into an int64_t. A double |
| 1404 | // has 52 bits of preceision. An int64_t has 63. Casting |
| 1405 | // INT64_MAX to a double actually causes a round up which |
| 1406 | // is bad and wrong for the comparison because it will |
| 1407 | // allow conversion of doubles that can't fit into a |
| 1408 | // uint64_t. To remedy this INT64_MAX - 0x7ff is used as |
| 1409 | // the cutoff point as if that rounds up in conversion to |
| 1410 | // double it will still be less than INT64_MAX. 0x7ff is |
| 1411 | // picked because it has 11 bits set. |
| 1412 | // |
| 1413 | // INT64_MAX seconds is on the order of 10 billion years, |
| 1414 | // and the earth is less than 5 billion years old, so for |
| 1415 | // most uses this conversion error won't occur even though |
| 1416 | // doubles can go much larger. |
| 1417 | // |
| 1418 | // Without the 0x7ff there is a ~30 minute range of time |
| 1419 | // values 10 billion years in the past and in the future |
| 1420 | // where this this code would go wrong. |
| 1421 | const double d = pDecodedItem->val.dfnum; |
| 1422 | if(d > (double)(INT64_MAX - 0x7ff)) { |
| 1423 | nReturn = QCBOR_ERR_DATE_OVERFLOW; |
| 1424 | goto Done; |
| 1425 | } |
| 1426 | pDecodedItem->val.epochDate.nSeconds = (int64_t)d; |
| 1427 | pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds; |
| 1428 | } |
| 1429 | break; |
| 1430 | |
| 1431 | default: |
| 1432 | nReturn = QCBOR_ERR_BAD_OPT_TAG; |
| 1433 | goto Done; |
| 1434 | } |
| 1435 | pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH; |
| 1436 | |
| 1437 | Done: |
| 1438 | return nReturn; |
| 1439 | } |
| 1440 | |
| 1441 | |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 1442 | /* |
| 1443 | Mostly just assign the right data type for the bignum. |
| 1444 | */ |
| 1445 | inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem) |
| 1446 | { |
| 1447 | // Stack Use: UsefulBuf 1 -- 16 |
| 1448 | if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) { |
| 1449 | return QCBOR_ERR_BAD_OPT_TAG; |
| 1450 | } |
| 1451 | const UsefulBufC Temp = pDecodedItem->val.string; |
| 1452 | pDecodedItem->val.bigNum = Temp; |
| 1453 | const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM); |
| 1454 | pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM |
| 1455 | : QCBOR_TYPE_NEGBIGNUM); |
| 1456 | return QCBOR_SUCCESS; |
| 1457 | } |
| 1458 | |
| 1459 | |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1460 | #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA |
| 1461 | /* |
| 1462 | Decode decimal fractions and big floats. |
| 1463 | |
| 1464 | When called pDecodedItem must be the array that is tagged as a big |
| 1465 | float or decimal fraction, the array that has the two members, the |
| 1466 | exponent and mantissa. |
| 1467 | |
| 1468 | This will fetch and decode the exponent and mantissa and put the |
| 1469 | result back into pDecodedItem. |
| 1470 | */ |
| 1471 | inline static QCBORError |
| 1472 | QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem) |
| 1473 | { |
| 1474 | QCBORError nReturn; |
| 1475 | |
| 1476 | // --- Make sure it is an array; track nesting level of members --- |
| 1477 | if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) { |
| 1478 | nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA; |
| 1479 | goto Done; |
| 1480 | } |
| 1481 | |
| 1482 | // A check for pDecodedItem->val.uCount == 2 would work for |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1483 | // definite length arrays, but not for indefnite. Instead remember |
| 1484 | // the nesting level the two integers must be at, which is one |
| 1485 | // deeper than that of the array. |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1486 | const int nNestLevel = pDecodedItem->uNestingLevel + 1; |
| 1487 | |
| 1488 | // --- Is it a decimal fraction or a bigfloat? --- |
| 1489 | const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION); |
| 1490 | pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT; |
| 1491 | |
| 1492 | // --- Get the exponent --- |
| 1493 | QCBORItem exponentItem; |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1494 | nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem); |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1495 | if(nReturn != QCBOR_SUCCESS) { |
| 1496 | goto Done; |
| 1497 | } |
| 1498 | if(exponentItem.uNestingLevel != nNestLevel) { |
| 1499 | // Array is empty or a map/array encountered when expecting an int |
| 1500 | nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA; |
| 1501 | goto Done; |
| 1502 | } |
| 1503 | if(exponentItem.uDataType == QCBOR_TYPE_INT64) { |
| 1504 | // Data arriving as an unsigned int < INT64_MAX has been converted |
| 1505 | // to QCBOR_TYPE_INT64 and thus handled here. This is also means |
| 1506 | // that the only data arriving here of type QCBOR_TYPE_UINT64 data |
| 1507 | // will be too large for this to handle and thus an error that will |
| 1508 | // get handled in the next else. |
| 1509 | pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64; |
| 1510 | } else { |
| 1511 | // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX |
| 1512 | nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA; |
| 1513 | goto Done; |
| 1514 | } |
| 1515 | |
| 1516 | // --- Get the mantissa --- |
| 1517 | QCBORItem mantissaItem; |
| 1518 | nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL); |
| 1519 | if(nReturn != QCBOR_SUCCESS) { |
| 1520 | goto Done; |
| 1521 | } |
| 1522 | if(mantissaItem.uNestingLevel != nNestLevel) { |
| 1523 | // Mantissa missing or map/array encountered when expecting number |
| 1524 | nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA; |
| 1525 | goto Done; |
| 1526 | } |
| 1527 | if(mantissaItem.uDataType == QCBOR_TYPE_INT64) { |
| 1528 | // Data arriving as an unsigned int < INT64_MAX has been converted |
| 1529 | // to QCBOR_TYPE_INT64 and thus handled here. This is also means |
| 1530 | // that the only data arriving here of type QCBOR_TYPE_UINT64 data |
| 1531 | // will be too large for this to handle and thus an error that |
| 1532 | // will get handled in an else below. |
| 1533 | pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64; |
| 1534 | } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) { |
| 1535 | // Got a good big num mantissa |
| 1536 | pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum; |
| 1537 | // Depends on numbering of QCBOR_TYPE_XXX |
Laurence Lundblade | 06350ea | 2020-01-27 19:32:40 -0800 | [diff] [blame] | 1538 | pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType + |
| 1539 | mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM + |
| 1540 | 1); |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1541 | } else { |
| 1542 | // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX |
| 1543 | nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA; |
| 1544 | goto Done; |
| 1545 | } |
| 1546 | |
| 1547 | // --- Check that array only has the two numbers --- |
| 1548 | if(mantissaItem.uNextNestLevel == nNestLevel) { |
| 1549 | // Extra items in the decimal fraction / big num |
| 1550 | nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA; |
| 1551 | goto Done; |
| 1552 | } |
| 1553 | |
| 1554 | Done: |
| 1555 | |
| 1556 | return nReturn; |
| 1557 | } |
| 1558 | #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */ |
| 1559 | |
| 1560 | |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 1561 | |
| 1562 | /* |
| 1563 | */ |
| 1564 | inline static QCBORError DecodeURI(QCBORItem *pDecodedItem) |
| 1565 | { |
| 1566 | if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) { |
| 1567 | return QCBOR_ERR_BAD_OPT_TAG; |
| 1568 | } |
| 1569 | pDecodedItem->uDataType = QCBOR_TYPE_URI; |
| 1570 | return QCBOR_SUCCESS; |
| 1571 | } |
| 1572 | |
| 1573 | |
| 1574 | inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem) |
| 1575 | { |
| 1576 | if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) { |
| 1577 | return QCBOR_ERR_BAD_OPT_TAG; |
| 1578 | } |
| 1579 | pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL; |
| 1580 | return QCBOR_SUCCESS; |
| 1581 | } |
| 1582 | |
| 1583 | |
| 1584 | inline static QCBORError DecodeB64(QCBORItem *pDecodedItem) |
| 1585 | { |
| 1586 | if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) { |
| 1587 | return QCBOR_ERR_BAD_OPT_TAG; |
| 1588 | } |
| 1589 | pDecodedItem->uDataType = QCBOR_TYPE_BASE64; |
| 1590 | return QCBOR_SUCCESS; |
| 1591 | } |
| 1592 | |
| 1593 | |
| 1594 | inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem) |
| 1595 | { |
| 1596 | if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) { |
| 1597 | return QCBOR_ERR_BAD_OPT_TAG; |
| 1598 | } |
| 1599 | pDecodedItem->uDataType = QCBOR_TYPE_REGEX; |
| 1600 | return QCBOR_SUCCESS; |
| 1601 | } |
| 1602 | |
| 1603 | |
| 1604 | inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem) |
| 1605 | { |
| 1606 | if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) { |
| 1607 | pDecodedItem->uDataType = QCBOR_TYPE_MIME; |
| 1608 | } else if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) { |
| 1609 | pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME; |
| 1610 | } else { |
| 1611 | return QCBOR_ERR_BAD_OPT_TAG; |
| 1612 | } |
| 1613 | return QCBOR_SUCCESS; |
| 1614 | } |
| 1615 | |
| 1616 | |
| 1617 | /* |
| 1618 | */ |
| 1619 | inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem) |
| 1620 | { |
| 1621 | if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) { |
| 1622 | return QCBOR_ERR_BAD_OPT_TAG; |
| 1623 | } |
| 1624 | pDecodedItem->uDataType = QCBOR_TYPE_UUID; |
| 1625 | return QCBOR_SUCCESS; |
| 1626 | } |
| 1627 | |
| 1628 | |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1629 | /* |
Laurence Lundblade | 844bb5c | 2020-03-01 17:27:25 -0800 | [diff] [blame] | 1630 | Public function, see header qcbor/qcbor_decode.h file |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1631 | */ |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1632 | QCBORError |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1633 | QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem) |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1634 | { |
| 1635 | QCBORError nReturn; |
| 1636 | |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1637 | nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem); |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1638 | if(nReturn != QCBOR_SUCCESS) { |
| 1639 | goto Done; |
| 1640 | } |
| 1641 | |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1642 | for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) { |
| 1643 | switch(pDecodedItem->uTags[i] ) { |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1644 | |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1645 | case CBOR_TAG_DATE_STRING: |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1646 | nReturn = DecodeDateString(pDecodedItem); |
| 1647 | break; |
| 1648 | |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1649 | case CBOR_TAG_DATE_EPOCH: |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1650 | nReturn = DecodeDateEpoch(pDecodedItem); |
| 1651 | break; |
| 1652 | |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1653 | case CBOR_TAG_POS_BIGNUM: |
| 1654 | case CBOR_TAG_NEG_BIGNUM: |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1655 | nReturn = DecodeBigNum(pDecodedItem); |
| 1656 | break; |
| 1657 | |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1658 | #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA |
| 1659 | case CBOR_TAG_DECIMAL_FRACTION: |
| 1660 | case CBOR_TAG_BIGFLOAT: |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1661 | // For aggregate tagged types, what goes into pTags is only collected |
| 1662 | // from the surrounding data item, not the contents, so pTags is not |
| 1663 | // passed on here. |
| 1664 | |
| 1665 | nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem); |
| 1666 | break; |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1667 | #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */ |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1668 | |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1669 | case CBOR_TAG_URI: |
| 1670 | nReturn = DecodeURI(pDecodedItem); |
| 1671 | break; |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1672 | |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 1673 | case CBOR_TAG_B64URL: |
| 1674 | nReturn = DecodeB64URL(pDecodedItem); |
| 1675 | break; |
| 1676 | |
| 1677 | case CBOR_TAG_B64: |
| 1678 | nReturn = DecodeB64(pDecodedItem); |
| 1679 | break; |
| 1680 | |
| 1681 | case CBOR_TAG_MIME: |
| 1682 | case CBOR_TAG_BINARY_MIME: |
| 1683 | nReturn = DecodeMIME(pDecodedItem); |
| 1684 | break; |
| 1685 | |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1686 | case CBOR_TAG_REGEX: |
| 1687 | nReturn = DecodeRegex(pDecodedItem); |
| 1688 | break; |
| 1689 | |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 1690 | case CBOR_TAG_BIN_UUID: |
| 1691 | nReturn = DecodeUUID(pDecodedItem); |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1692 | break; |
| 1693 | |
Laurence Lundblade | c75e68b | 2020-06-15 20:34:46 -0700 | [diff] [blame] | 1694 | case CBOR_TAG_INVALID16: |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 1695 | // The end of the tag list or no tags |
| 1696 | // Successful exit from the loop. |
| 1697 | goto Done; |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 1698 | |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1699 | default: |
| 1700 | // A tag that is not understood |
| 1701 | // A successful exit from the loop |
| 1702 | goto Done; |
| 1703 | |
| 1704 | } |
| 1705 | if(nReturn != QCBOR_SUCCESS) { |
| 1706 | goto Done; |
| 1707 | } |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1708 | } |
| 1709 | |
| 1710 | Done: |
| 1711 | if(nReturn != QCBOR_SUCCESS) { |
| 1712 | pDecodedItem->uDataType = QCBOR_TYPE_NONE; |
| 1713 | pDecodedItem->uLabelType = QCBOR_TYPE_NONE; |
| 1714 | } |
| 1715 | return nReturn; |
| 1716 | } |
| 1717 | |
| 1718 | |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1719 | QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem) |
| 1720 | { |
| 1721 | const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf)); |
| 1722 | |
| 1723 | QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem); |
| 1724 | |
| 1725 | UsefulInputBuf_Seek(&(pMe->InBuf), uOffset); |
| 1726 | |
| 1727 | return uErr; |
| 1728 | } |
| 1729 | |
| 1730 | |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1731 | /* |
Laurence Lundblade | 844bb5c | 2020-03-01 17:27:25 -0800 | [diff] [blame] | 1732 | Public function, see header qcbor/qcbor_decode.h file |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1733 | */ |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1734 | QCBORError |
| 1735 | QCBORDecode_GetNextWithTags(QCBORDecodeContext *me, |
| 1736 | QCBORItem *pDecodedItem, |
| 1737 | QCBORTagListOut *pTags) |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 1738 | { |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1739 | QCBORError nReturn; |
| 1740 | |
| 1741 | nReturn = QCBORDecode_GetNext(me, pDecodedItem); |
| 1742 | if(nReturn != QCBOR_SUCCESS) { |
| 1743 | return nReturn; |
| 1744 | } |
| 1745 | |
| 1746 | if(pTags != NULL) { |
| 1747 | pTags->uNumUsed = 0; |
| 1748 | for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) { |
Laurence Lundblade | c75e68b | 2020-06-15 20:34:46 -0700 | [diff] [blame] | 1749 | if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) { |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1750 | break; |
| 1751 | } |
| 1752 | if(pTags->uNumUsed >= pTags->uNumAllocated) { |
| 1753 | return QCBOR_ERR_TOO_MANY_TAGS; |
| 1754 | } |
| 1755 | pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]); |
| 1756 | pTags->uNumUsed++; |
| 1757 | } |
| 1758 | } |
| 1759 | |
| 1760 | return QCBOR_SUCCESS; |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 1761 | } |
| 1762 | |
| 1763 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1764 | /* |
Laurence Lundblade | 6de3706 | 2018-10-15 12:22:42 +0530 | [diff] [blame] | 1765 | Decoding items is done in 5 layered functions, one calling the |
Laurence Lundblade | 0fb2f64 | 2018-10-11 19:33:35 +0530 | [diff] [blame] | 1766 | next one down. If a layer has no work to do for a particular item |
| 1767 | it returns quickly. |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1768 | |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1769 | - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes |
| 1770 | tagged data items, turning them into the local C representation. |
| 1771 | For the most simple it is just associating a QCBOR_TYPE with the data. For |
| 1772 | the complex ones that an aggregate of data items, there is some further |
| 1773 | decoding and a little bit of recursion. |
| 1774 | |
| 1775 | - QCBORDecode_GetNextMapOrArray - This manages the beginnings and |
Laurence Lundblade | 0fb2f64 | 2018-10-11 19:33:35 +0530 | [diff] [blame] | 1776 | ends of maps and arrays. It tracks descending into and ascending |
Laurence Lundblade | 6de3706 | 2018-10-15 12:22:42 +0530 | [diff] [blame] | 1777 | out of maps/arrays. It processes all breaks that terminate |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 1778 | indefinite length maps and arrays. |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1779 | |
Laurence Lundblade | 0fb2f64 | 2018-10-11 19:33:35 +0530 | [diff] [blame] | 1780 | - GetNext_MapEntry -- This handles the combining of two |
| 1781 | items, the label and the data, that make up a map entry. |
| 1782 | It only does work on maps. It combines the label and data |
| 1783 | items into one labeled item. |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1784 | |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1785 | - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the |
| 1786 | tags into bit flags associated with the data item. No actual decoding |
| 1787 | of the contents of the tagged item is performed here. |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1788 | |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1789 | - GetNext_FullItem -- This assembles the sub-items that make up |
Laurence Lundblade | 0fb2f64 | 2018-10-11 19:33:35 +0530 | [diff] [blame] | 1790 | an indefinte length string into one string item. It uses the |
Laurence Lundblade | 6de3706 | 2018-10-15 12:22:42 +0530 | [diff] [blame] | 1791 | string allocater to create contiguous space for the item. It |
| 1792 | processes all breaks that are part of indefinite length strings. |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1793 | |
Laurence Lundblade | 59289e5 | 2019-12-30 13:44:37 -0800 | [diff] [blame] | 1794 | - GetNext_Item -- This decodes the atomic data items in CBOR. Each |
| 1795 | atomic data item has a "major type", an integer "argument" and optionally |
| 1796 | some content. For text and byte strings, the content is the bytes |
| 1797 | that make up the string. These are the smallest data items that are |
| 1798 | considered to be well-formed. The content may also be other data items in |
| 1799 | the case of aggregate types. They are not handled in this layer. |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1800 | |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 1801 | Roughly this takes 300 bytes of stack for vars. Need to |
| 1802 | evaluate this more carefully and correctly. |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1803 | |
Laurence Lundblade | 0fb2f64 | 2018-10-11 19:33:35 +0530 | [diff] [blame] | 1804 | */ |
| 1805 | |
| 1806 | |
| 1807 | /* |
Laurence Lundblade | 844bb5c | 2020-03-01 17:27:25 -0800 | [diff] [blame] | 1808 | Public function, see header qcbor/qcbor_decode.h file |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1809 | */ |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1810 | int QCBORDecode_IsTagged(QCBORDecodeContext *me, |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 1811 | const QCBORItem *pItem, |
| 1812 | uint64_t uTag) |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 1813 | { |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1814 | for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) { |
Laurence Lundblade | c75e68b | 2020-06-15 20:34:46 -0700 | [diff] [blame] | 1815 | if(pItem->uTags[i] == CBOR_TAG_INVALID16) { |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1816 | break; |
| 1817 | } |
| 1818 | if(ConvertTag(me, pItem->uTags[i]) == uTag) { |
| 1819 | return 1; |
| 1820 | } |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 1821 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1822 | |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 1823 | return 0; |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 1824 | } |
| 1825 | |
| 1826 | |
| 1827 | /* |
Laurence Lundblade | 844bb5c | 2020-03-01 17:27:25 -0800 | [diff] [blame] | 1828 | Public function, see header qcbor/qcbor_decode.h file |
Laurence Lundblade | dbe6f21 | 2018-10-28 11:37:53 +0700 | [diff] [blame] | 1829 | */ |
Laurence Lundblade | 30816f2 | 2018-11-10 13:40:22 +0700 | [diff] [blame] | 1830 | QCBORError QCBORDecode_Finish(QCBORDecodeContext *me) |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1831 | { |
Laurence Lundblade | 06350ea | 2020-01-27 19:32:40 -0800 | [diff] [blame] | 1832 | QCBORError nReturn = QCBOR_SUCCESS; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1833 | |
Laurence Lundblade | 20b533d | 2018-10-08 20:44:53 +0800 | [diff] [blame] | 1834 | // Error out if all the maps/arrays are not closed out |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 1835 | if(!DecodeNesting_IsAtTop(&(me->nesting))) { |
Laurence Lundblade | 20b533d | 2018-10-08 20:44:53 +0800 | [diff] [blame] | 1836 | nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN; |
| 1837 | goto Done; |
| 1838 | } |
| 1839 | |
| 1840 | // Error out if not all the bytes are consumed |
| 1841 | if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) { |
| 1842 | nReturn = QCBOR_ERR_EXTRA_BYTES; |
| 1843 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1844 | |
Laurence Lundblade | 20b533d | 2018-10-08 20:44:53 +0800 | [diff] [blame] | 1845 | Done: |
Laurence Lundblade | 6de3706 | 2018-10-15 12:22:42 +0530 | [diff] [blame] | 1846 | // Call the destructor for the string allocator if there is one. |
Laurence Lundblade | 20b533d | 2018-10-08 20:44:53 +0800 | [diff] [blame] | 1847 | // Always called, even if there are errors; always have to clean up |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 1848 | StringAllocator_Destruct(&(me->StringAllocator)); |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1849 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 1850 | return nReturn; |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1851 | } |
| 1852 | |
| 1853 | |
Laurence Lundblade | c75e68b | 2020-06-15 20:34:46 -0700 | [diff] [blame] | 1854 | /* |
| 1855 | Public function, see header qcbor/qcbor_decode.h file |
| 1856 | */ |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 1857 | uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe, |
| 1858 | const QCBORItem *pItem, |
| 1859 | unsigned int uIndex) |
Laurence Lundblade | c75e68b | 2020-06-15 20:34:46 -0700 | [diff] [blame] | 1860 | { |
| 1861 | if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) { |
| 1862 | return CBOR_TAG_INVALID16; |
| 1863 | } else if(pItem->uTags[uIndex] <= QCBOR_LAST_UNMAPPED_TAG) { |
| 1864 | return pItem->uTags[uIndex]; |
| 1865 | } else if(pItem->uTags[uIndex] < QCBOR_NUM_MAPPED_TAGS + QCBOR_LAST_UNMAPPED_TAG) { |
| 1866 | return pMe->auMappedTags[pItem->uTags[uIndex] - QCBOR_LAST_UNMAPPED_TAG]; |
| 1867 | } else { |
| 1868 | return CBOR_TAG_INVALID16; |
| 1869 | } |
| 1870 | } |
| 1871 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1872 | |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1873 | /* |
| 1874 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1875 | Decoder errors handled in this file |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1876 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1877 | - Hit end of input before it was expected while decoding type and |
| 1878 | number QCBOR_ERR_HIT_END |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1879 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1880 | - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1881 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1882 | - Hit end of input while decoding a text or byte string |
| 1883 | QCBOR_ERR_HIT_END |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1884 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1885 | - Encountered conflicting tags -- e.g., an item is tagged both a date |
| 1886 | string and an epoch date QCBOR_ERR_UNSUPPORTED |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1887 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1888 | - Encontered an array or mapp that has too many items |
| 1889 | QCBOR_ERR_ARRAY_TOO_LONG |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1890 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1891 | - Encountered array/map nesting that is too deep |
| 1892 | QCBOR_ERR_ARRAY_NESTING_TOO_DEEP |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1893 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1894 | - An epoch date > INT64_MAX or < INT64_MIN was encountered |
| 1895 | QCBOR_ERR_DATE_OVERFLOW |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1896 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1897 | - The type of a map label is not a string or int |
| 1898 | QCBOR_ERR_MAP_LABEL_TYPE |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1899 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1900 | - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1901 | |
Laurence Lundblade | b69cad7 | 2018-09-13 11:09:01 -0700 | [diff] [blame] | 1902 | */ |
| 1903 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 1904 | |
| 1905 | |
Laurence Lundblade | f653166 | 2018-12-04 10:42:22 +0900 | [diff] [blame] | 1906 | |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 1907 | /* =========================================================================== |
| 1908 | MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1909 | |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 1910 | This implements a simple sting allocator for indefinite length |
| 1911 | strings that can be enabled by calling QCBORDecode_SetMemPool(). It |
| 1912 | implements the function type QCBORStringAllocate and allows easy |
| 1913 | use of it. |
Laurence Lundblade | f653166 | 2018-12-04 10:42:22 +0900 | [diff] [blame] | 1914 | |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 1915 | This particular allocator is built-in for convenience. The caller |
| 1916 | can implement their own. All of this following code will get |
| 1917 | dead-stripped if QCBORDecode_SetMemPool() is not called. |
| 1918 | |
| 1919 | This is a very primitive memory allocator. It does not track |
| 1920 | individual allocations, only a high-water mark. A free or |
| 1921 | reallocation must be of the last chunk allocated. |
| 1922 | |
| 1923 | The size of the pool and offset to free memory are packed into the |
| 1924 | first 8 bytes of the memory pool so we don't have to keep them in |
| 1925 | the decode context. Since the address of the pool may not be |
| 1926 | aligned, they have to be packed and unpacked as if they were |
| 1927 | serialized data of the wire or such. |
| 1928 | |
| 1929 | The sizes packed in are uint32_t to be the same on all CPU types |
| 1930 | and simplify the code. |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1931 | ========================================================================== */ |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 1932 | |
| 1933 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1934 | static inline int |
| 1935 | MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset) |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 1936 | { |
| 1937 | // Use of UsefulInputBuf is overkill, but it is convenient. |
| 1938 | UsefulInputBuf UIB; |
| 1939 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1940 | // Just assume the size here. It was checked during SetUp so |
| 1941 | // the assumption is safe. |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 1942 | UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE}); |
| 1943 | *puPoolSize = UsefulInputBuf_GetUint32(&UIB); |
| 1944 | *puFreeOffset = UsefulInputBuf_GetUint32(&UIB); |
| 1945 | return UsefulInputBuf_GetError(&UIB); |
| 1946 | } |
| 1947 | |
| 1948 | |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1949 | static inline int |
| 1950 | MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset) |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 1951 | { |
| 1952 | // Use of UsefulOutBuf is overkill, but convenient. The |
| 1953 | // length check performed here is useful. |
| 1954 | UsefulOutBuf UOB; |
| 1955 | |
| 1956 | UsefulOutBuf_Init(&UOB, Pool); |
| 1957 | UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool |
| 1958 | UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position |
| 1959 | return UsefulOutBuf_GetError(&UOB); |
| 1960 | } |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 1961 | |
| 1962 | |
| 1963 | /* |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 1964 | Internal function for an allocation, reallocation free and destuct. |
| 1965 | |
| 1966 | Having only one function rather than one each per mode saves space in |
| 1967 | QCBORDecodeContext. |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1968 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 1969 | Code Reviewers: THIS FUNCTION DOES POINTER MATH |
| 1970 | */ |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 1971 | static UsefulBuf |
| 1972 | MemPool_Function(void *pPool, void *pMem, size_t uNewSize) |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 1973 | { |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 1974 | UsefulBuf ReturnValue = NULLUsefulBuf; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 1975 | |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 1976 | uint32_t uPoolSize; |
| 1977 | uint32_t uFreeOffset; |
| 1978 | |
| 1979 | if(uNewSize > UINT32_MAX) { |
| 1980 | // This allocator is only good up to 4GB. This check should |
| 1981 | // optimize out if sizeof(size_t) == sizeof(uint32_t) |
| 1982 | goto Done; |
| 1983 | } |
| 1984 | const uint32_t uNewSize32 = (uint32_t)uNewSize; |
| 1985 | |
| 1986 | if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) { |
| 1987 | goto Done; |
| 1988 | } |
| 1989 | |
| 1990 | if(uNewSize) { |
| 1991 | if(pMem) { |
| 1992 | // REALLOCATION MODE |
| 1993 | // Calculate pointer to the end of the memory pool. It is |
| 1994 | // assumed that pPool + uPoolSize won't wrap around by |
| 1995 | // assuming the caller won't pass a pool buffer in that is |
| 1996 | // not in legitimate memory space. |
| 1997 | const void *pPoolEnd = (uint8_t *)pPool + uPoolSize; |
| 1998 | |
| 1999 | // Check that the pointer for reallocation is in the range of the |
| 2000 | // pool. This also makes sure that pointer math further down |
| 2001 | // doesn't wrap under or over. |
| 2002 | if(pMem >= pPool && pMem < pPoolEnd) { |
| 2003 | // Offset to start of chunk for reallocation. This won't |
| 2004 | // wrap under because of check that pMem >= pPool. Cast |
| 2005 | // is safe because the pool is always less than UINT32_MAX |
| 2006 | // because of check in QCBORDecode_SetMemPool(). |
| 2007 | const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool); |
| 2008 | |
| 2009 | // Check to see if the allocation will fit. uPoolSize - |
| 2010 | // uMemOffset will not wrap under because of check that |
| 2011 | // pMem is in the range of the uPoolSize by check above. |
| 2012 | if(uNewSize <= uPoolSize - uMemOffset) { |
| 2013 | ReturnValue.ptr = pMem; |
| 2014 | ReturnValue.len = uNewSize; |
| 2015 | |
| 2016 | // Addition won't wrap around over because uNewSize was |
| 2017 | // checked to be sure it is less than the pool size. |
| 2018 | uFreeOffset = uMemOffset + uNewSize32; |
| 2019 | } |
| 2020 | } |
| 2021 | } else { |
| 2022 | // ALLOCATION MODE |
| 2023 | // uPoolSize - uFreeOffset will not underflow because this |
| 2024 | // pool implementation makes sure uFreeOffset is always |
| 2025 | // smaller than uPoolSize through this check here and |
| 2026 | // reallocation case. |
| 2027 | if(uNewSize <= uPoolSize - uFreeOffset) { |
| 2028 | ReturnValue.len = uNewSize; |
| 2029 | ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset; |
Laurence Lundblade | 06350ea | 2020-01-27 19:32:40 -0800 | [diff] [blame] | 2030 | uFreeOffset += (uint32_t)uNewSize; |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 2031 | } |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 2032 | } |
| 2033 | } else { |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 2034 | if(pMem) { |
| 2035 | // FREE MODE |
| 2036 | // Cast is safe because of limit on pool size in |
| 2037 | // QCBORDecode_SetMemPool() |
| 2038 | uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool); |
| 2039 | } else { |
| 2040 | // DESTRUCT MODE |
| 2041 | // Nothing to do for this allocator |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 2042 | } |
| 2043 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 2044 | |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 2045 | UsefulBuf Pool = {pPool, uPoolSize}; |
| 2046 | MemPool_Pack(Pool, uFreeOffset); |
| 2047 | |
| 2048 | Done: |
| 2049 | return ReturnValue; |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 2050 | } |
| 2051 | |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 2052 | |
Laurence Lundblade | f653166 | 2018-12-04 10:42:22 +0900 | [diff] [blame] | 2053 | /* |
Laurence Lundblade | 844bb5c | 2020-03-01 17:27:25 -0800 | [diff] [blame] | 2054 | Public function, see header qcbor/qcbor_decode.h file |
Laurence Lundblade | f653166 | 2018-12-04 10:42:22 +0900 | [diff] [blame] | 2055 | */ |
Laurence Lundblade | ee85174 | 2020-01-08 08:37:05 -0800 | [diff] [blame] | 2056 | QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe, |
| 2057 | UsefulBuf Pool, |
| 2058 | bool bAllStrings) |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 2059 | { |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 2060 | // The pool size and free mem offset are packed into the beginning |
| 2061 | // of the pool memory. This compile time check make sure the |
| 2062 | // constant in the header is correct. This check should optimize |
| 2063 | // down to nothing. |
| 2064 | if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) { |
Laurence Lundblade | 30816f2 | 2018-11-10 13:40:22 +0700 | [diff] [blame] | 2065 | return QCBOR_ERR_BUFFER_TOO_SMALL; |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 2066 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 2067 | |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 2068 | // The pool size and free offset packed in to the beginning of pool |
| 2069 | // memory are only 32-bits. This check will optimize out on 32-bit |
| 2070 | // machines. |
| 2071 | if(Pool.len > UINT32_MAX) { |
| 2072 | return QCBOR_ERR_BUFFER_TOO_LARGE; |
| 2073 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 2074 | |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 2075 | // This checks that the pool buffer given is big enough. |
| 2076 | if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) { |
| 2077 | return QCBOR_ERR_BUFFER_TOO_SMALL; |
| 2078 | } |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 2079 | |
Laurence Lundblade | 1d7eb63 | 2019-02-17 17:23:38 -0800 | [diff] [blame] | 2080 | pMe->StringAllocator.pfAllocator = MemPool_Function; |
| 2081 | pMe->StringAllocator.pAllocateCxt = Pool.ptr; |
| 2082 | pMe->bStringAllocateAll = bAllStrings; |
Laurence Lundblade | 3aee3a3 | 2018-12-17 16:17:45 -0800 | [diff] [blame] | 2083 | |
Laurence Lundblade | 30816f2 | 2018-11-10 13:40:22 +0700 | [diff] [blame] | 2084 | return QCBOR_SUCCESS; |
Laurence Lundblade | 041ffa5 | 2018-10-07 11:43:51 +0700 | [diff] [blame] | 2085 | } |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2086 | |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2087 | |
| 2088 | |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2089 | #include <stdio.h> |
| 2090 | void printdecode(QCBORDecodeContext *pMe, const char *szName) |
| 2091 | { |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 2092 | printf("---%s--%d--%d--\nLevel Count Type Offset SaveCount MapMode\n", |
| 2093 | szName, |
| 2094 | (uint32_t)pMe->InBuf.cursor, |
| 2095 | (uint32_t)pMe->InBuf.UB.len); |
Laurence Lundblade | 64b607e | 2020-05-13 13:05:57 -0700 | [diff] [blame] | 2096 | for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) { |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 2097 | if(&(pMe->nesting.pMapsAndArrays[i]) > pMe->nesting.pCurrent) { |
| 2098 | break; |
| 2099 | } |
Laurence Lundblade | 64b607e | 2020-05-13 13:05:57 -0700 | [diff] [blame] | 2100 | printf("%2s %2d %5d %s %6u %2d %d\n", |
| 2101 | pMe->nesting.pCurrentMap == &(pMe->nesting.pMapsAndArrays[i]) ? "->": " ", |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2102 | i, |
| 2103 | pMe->nesting.pMapsAndArrays[i].uCount, |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 2104 | pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_MAP ? " map" : |
| 2105 | (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_ARRAY ? "array" : |
| 2106 | (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_NONE ? " none" : "?????")), |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2107 | pMe->nesting.pMapsAndArrays[i].uOffset, |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 2108 | pMe->nesting.pMapsAndArrays[i].uSaveCount, |
| 2109 | pMe->nesting.pMapsAndArrays[i].uMapMode |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2110 | ); |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 2111 | |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2112 | } |
Laurence Lundblade | 64b607e | 2020-05-13 13:05:57 -0700 | [diff] [blame] | 2113 | printf("\n"); |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2114 | } |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2115 | |
| 2116 | |
| 2117 | /* |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2118 | Consume an entire map or array (and do next to |
| 2119 | nothing for non-aggregate types). |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2120 | */ |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 2121 | static inline QCBORError |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2122 | ConsumeItem(QCBORDecodeContext *pMe, |
| 2123 | const QCBORItem *pItemToConsume, |
| 2124 | uint_fast8_t *puNextNestLevel) |
| 2125 | { |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2126 | QCBORError uReturn; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2127 | QCBORItem Item; |
| 2128 | |
| 2129 | printdecode(pMe, "ConsumeItem"); |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2130 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 2131 | if(IsMapOrArray(pItemToConsume->uDataType)) { |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2132 | /* There is only real work to do for maps and arrays */ |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2133 | |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2134 | /* This works for definite and indefinite length |
| 2135 | * maps and arrays by using the nesting level |
| 2136 | */ |
| 2137 | do { |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2138 | uReturn = QCBORDecode_GetNext(pMe, &Item); |
| 2139 | if(uReturn != QCBOR_SUCCESS) { |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2140 | goto Done; |
| 2141 | } |
| 2142 | } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel); |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2143 | |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2144 | if(puNextNestLevel != NULL) { |
| 2145 | *puNextNestLevel = Item.uNextNestLevel; |
| 2146 | } |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2147 | uReturn = QCBOR_SUCCESS; |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2148 | |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2149 | } else { |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2150 | /* item_to_consume is not a map or array */ |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2151 | if(puNextNestLevel != NULL) { |
| 2152 | /* Just pass the nesting level through */ |
| 2153 | *puNextNestLevel = pItemToConsume->uNextNestLevel; |
| 2154 | } |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2155 | uReturn = QCBOR_SUCCESS; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2156 | } |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2157 | |
| 2158 | Done: |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2159 | return uReturn; |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2160 | } |
| 2161 | |
| 2162 | |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2163 | /* Return true if the labels in Item1 and Item2 are the same. |
| 2164 | Works only for integer and string labels. Returns false |
| 2165 | for any other type. */ |
| 2166 | static inline bool |
| 2167 | MatchLabel(QCBORItem Item1, QCBORItem Item2) |
| 2168 | { |
| 2169 | if(Item1.uLabelType == QCBOR_TYPE_INT64) { |
| 2170 | if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) { |
| 2171 | return true; |
| 2172 | } |
| 2173 | } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) { |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2174 | if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) { |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2175 | return true; |
| 2176 | } |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2177 | } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) { |
Laurence Lundblade | fb492ea | 2020-05-02 11:14:07 -0700 | [diff] [blame] | 2178 | if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) { |
| 2179 | return true; |
| 2180 | } |
| 2181 | } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) { |
| 2182 | if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) { |
| 2183 | return true; |
| 2184 | } |
| 2185 | } |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2186 | |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2187 | /* Other label types are never matched */ |
| 2188 | return false; |
| 2189 | } |
| 2190 | |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2191 | |
| 2192 | /* |
| 2193 | Returns true if Item1 and Item2 are the same type |
| 2194 | or if either are of QCBOR_TYPE_ANY. |
| 2195 | */ |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2196 | static inline bool |
| 2197 | MatchType(QCBORItem Item1, QCBORItem Item2) |
| 2198 | { |
| 2199 | if(Item1.uDataType == Item2.uDataType) { |
| 2200 | return true; |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2201 | } else if(Item1.uDataType == QCBOR_TYPE_ANY) { |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2202 | return true; |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2203 | } else if(Item2.uDataType == QCBOR_TYPE_ANY) { |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2204 | return true; |
| 2205 | } |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2206 | return false; |
| 2207 | } |
| 2208 | |
| 2209 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2210 | /** |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2211 | \brief Search a map for a set of items. |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2212 | |
| 2213 | @param[in] pMe The decode context to search. |
| 2214 | @param[in,out] pItemArray The items to search for and the items found. |
| 2215 | @param[in] pCBContext Context for the not-found item call back |
| 2216 | @param[in] pfCallback Function to call on items not matched in pItemArray |
| 2217 | |
| 2218 | @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map |
| 2219 | |
| 2220 | @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label) were found for one of the labels being search for. This duplicate detection is only performed for items in pItemArray, not every item in the map. |
| 2221 | |
| 2222 | @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type. |
| 2223 | |
| 2224 | @retval Also errors returned by QCBORDecode_GetNext(). |
| 2225 | |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2226 | On input pItemArray contains a list of labels and data types |
| 2227 | of items to be found. |
| 2228 | |
| 2229 | On output the fully retrieved items are filled in with |
| 2230 | values and such. The label was matched, so it never changes. |
| 2231 | |
| 2232 | If an item was not found, its data type is set to none. |
| 2233 | |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2234 | */ |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 2235 | static QCBORError |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2236 | MapSearch(QCBORDecodeContext *pMe, |
| 2237 | QCBORItem *pItemArray, |
| 2238 | size_t *puOffset, |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2239 | void *pCBContext, |
| 2240 | QCBORItemCallback pfCallback) |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2241 | { |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2242 | QCBORError uReturn; |
Laurence Lundblade | fb492ea | 2020-05-02 11:14:07 -0700 | [diff] [blame] | 2243 | |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 2244 | QCBORDecodeNesting SaveNesting; |
| 2245 | DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting); |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2246 | |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2247 | // Reposition to search from the start of the map / array |
| 2248 | UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrentMap->uOffset); |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2249 | |
| 2250 | /* Loop over all the items in the map. They could be |
| 2251 | * deeply nested and this should handle both definite |
| 2252 | * and indefinite length maps and arrays, so this |
| 2253 | * adds some complexity. */ |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 2254 | const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting)); |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2255 | |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2256 | uint_fast8_t uNextNestLevel; |
| 2257 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2258 | uint64_t uFoundItemBitMap = 0; |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2259 | |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 2260 | /* Iterate over items in the map / array */ |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2261 | do { |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2262 | /* Remember offset of the item because sometimes it has to be returned */ |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2263 | const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf)); |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2264 | |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2265 | /* Get the item */ |
| 2266 | QCBORItem Item; |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2267 | uReturn = QCBORDecode_GetNext(pMe, &Item); |
| 2268 | if(uReturn != QCBOR_SUCCESS) { |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2269 | /* Got non-well-formed CBOR */ |
| 2270 | goto Done; |
| 2271 | } |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2272 | |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2273 | /* See if item has one of the labels that are of interest */ |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2274 | int nIndex; |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2275 | QCBORItem *pIterator; |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2276 | for(pIterator = pItemArray, nIndex = 0; pIterator->uLabelType != 0; pIterator++, nIndex++) { |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2277 | if(MatchLabel(Item, *pIterator)) { |
| 2278 | // A label match has been found |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2279 | if(uFoundItemBitMap & (0x01ULL << nIndex)) { |
| 2280 | uReturn = QCBOR_ERR_DUPLICATE_LABEL; |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2281 | goto Done; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2282 | } |
Laurence Lundblade | 830fbf9 | 2020-05-31 17:22:33 -0700 | [diff] [blame] | 2283 | /* Also try to match its type */ |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2284 | if(!MatchType(Item, *pIterator)) { |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2285 | uReturn = QCBOR_ERR_UNEXPECTED_TYPE; |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2286 | goto Done; |
| 2287 | } |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2288 | |
| 2289 | /* Successful match. Return the item. */ |
| 2290 | *pIterator = Item; |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2291 | uFoundItemBitMap |= 0x01ULL << nIndex; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2292 | if(puOffset) { |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2293 | *puOffset = uOffset; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2294 | } |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2295 | } else { |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2296 | /* Call the callback on unmatched labels */ |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2297 | /* It is tempting to do duplicate detection here, but that would |
| 2298 | require dynamic memory allocation because the number of labels |
| 2299 | that might be encountered is unbounded. |
| 2300 | */ |
| 2301 | if(pfCallback) { |
| 2302 | uReturn = (*pfCallback)(pCBContext, &Item); |
| 2303 | if(uReturn != QCBOR_SUCCESS) { |
| 2304 | goto Done; |
| 2305 | } |
| 2306 | } |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2307 | } |
| 2308 | } |
| 2309 | |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2310 | /* Consume the item whether matched or not. This |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2311 | does the work of traversing maps and array and |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2312 | everything in them. In this loop only the |
| 2313 | items at the current nesting level are examined |
| 2314 | to match the labels. */ |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2315 | uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel); |
| 2316 | if(uReturn) { |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2317 | goto Done; |
| 2318 | } |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2319 | |
| 2320 | } while (uNextNestLevel >= uMapNestLevel); |
| 2321 | |
| 2322 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2323 | uReturn = QCBOR_SUCCESS; |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2324 | |
| 2325 | const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf)); |
| 2326 | // Cast OK because encoded CBOR is limited to UINT32_MAX |
| 2327 | pMe->uMapEndOffset = (uint32_t)uEndOffset; |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2328 | |
Laurence Lundblade | fb492ea | 2020-05-02 11:14:07 -0700 | [diff] [blame] | 2329 | /* For all items not found, set the data type to QCBOR_TYPE_NONE */ |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2330 | int i; |
| 2331 | QCBORItem *pIterator; |
| 2332 | for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) { |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2333 | if(!(uFoundItemBitMap & (0x01ULL << i))) { |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2334 | pIterator->uDataType = QCBOR_TYPE_NONE; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2335 | } |
| 2336 | } |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2337 | |
| 2338 | Done: |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 2339 | DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting); |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2340 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2341 | return uReturn; |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2342 | } |
| 2343 | |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2344 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2345 | /* |
| 2346 | Public function, see header qcbor/qcbor_decode.h file |
| 2347 | */ |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2348 | void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe, |
| 2349 | int64_t nLabel, |
| 2350 | uint8_t uQcborType, |
| 2351 | QCBORItem *pItem) |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2352 | { |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2353 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 2354 | return; |
| 2355 | } |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2356 | |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2357 | QCBORItem OneItemSeach[2]; |
| 2358 | OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64; |
| 2359 | OneItemSeach[0].label.int64 = nLabel; |
| 2360 | OneItemSeach[0].uDataType = uQcborType; |
| 2361 | OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2362 | |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2363 | QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL); |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2364 | if(nReturn) { |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2365 | pMe->uLastError = (uint8_t)nReturn; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2366 | } |
| 2367 | |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2368 | if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) { |
| 2369 | pMe->uLastError = QCBOR_ERR_NOT_FOUND; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2370 | } |
| 2371 | |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2372 | *pItem = OneItemSeach[0]; |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2373 | } |
| 2374 | |
| 2375 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2376 | /* |
| 2377 | Public function, see header qcbor/qcbor_decode.h file |
| 2378 | */ |
Laurence Lundblade | da09597 | 2020-06-06 18:35:33 -0700 | [diff] [blame] | 2379 | void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe, |
| 2380 | const char *szLabel, |
| 2381 | uint8_t uQcborType, |
| 2382 | QCBORItem *pItem) |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2383 | { |
Laurence Lundblade | da09597 | 2020-06-06 18:35:33 -0700 | [diff] [blame] | 2384 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 2385 | return; |
| 2386 | } |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2387 | |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2388 | QCBORItem OneItemSeach[2]; |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2389 | OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING; |
| 2390 | OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel); |
| 2391 | OneItemSeach[0].uDataType = uQcborType; |
| 2392 | OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2393 | |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2394 | QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL); |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2395 | if(nReturn) { |
Laurence Lundblade | da09597 | 2020-06-06 18:35:33 -0700 | [diff] [blame] | 2396 | pMe->uLastError = (uint8_t)nReturn; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2397 | } |
| 2398 | |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2399 | if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) { |
Laurence Lundblade | da09597 | 2020-06-06 18:35:33 -0700 | [diff] [blame] | 2400 | pMe->uLastError = QCBOR_ERR_NOT_FOUND; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2401 | } |
| 2402 | |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2403 | *pItem = OneItemSeach[0]; |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2404 | } |
| 2405 | |
| 2406 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2407 | /** |
| 2408 | @param[in] TagSpec Specification for matching tags. |
| 2409 | @param[in] uDataType A QCBOR data type |
| 2410 | |
| 2411 | @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec |
| 2412 | @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec |
| 2413 | |
| 2414 | The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value. |
| 2415 | */ |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2416 | static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType) |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2417 | { |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2418 | if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) { |
| 2419 | /* Must match the tag */ |
| 2420 | if(uDataType == TagSpec.uTaggedType) { |
| 2421 | return QCBOR_SUCCESS; |
| 2422 | } |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2423 | } else { |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2424 | /* QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE or QCBOR_TAGSPEC_MATCH_EITHER */ |
| 2425 | /* Must check all the possible types for the tag content */ |
| 2426 | for(size_t i = 0; i < sizeof(TagSpec.uAllowedContentTypes); i++) { |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2427 | if(uDataType == TagSpec.uAllowedContentTypes[i]) { |
| 2428 | return QCBOR_SUCCESS; |
| 2429 | } |
| 2430 | } |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2431 | /* Didn't match any of the tag content types */ |
| 2432 | /* Check the tag for the either case */ |
| 2433 | if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_EITHER) { |
| 2434 | if(uDataType == TagSpec.uTaggedType) { |
| 2435 | return QCBOR_SUCCESS; |
| 2436 | } |
| 2437 | } |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2438 | } |
| 2439 | |
| 2440 | return QCBOR_ERR_UNEXPECTED_TYPE; |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2441 | } |
| 2442 | |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2443 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2444 | // Semi-private |
| 2445 | // TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN? |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2446 | void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe, |
| 2447 | int64_t nLabel, |
| 2448 | TagSpecification TagSpec, |
| 2449 | QCBORItem *pItem) |
| 2450 | { |
| 2451 | QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem); |
| 2452 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 2453 | return; |
| 2454 | } |
| 2455 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 2456 | pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType); |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2457 | } |
| 2458 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2459 | // Semi-private |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2460 | void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe, |
| 2461 | const char *szLabel, |
| 2462 | TagSpecification TagSpec, |
| 2463 | QCBORItem *pItem) |
| 2464 | { |
| 2465 | QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem); |
| 2466 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 2467 | return; |
| 2468 | } |
| 2469 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 2470 | pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType); |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2471 | } |
| 2472 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2473 | // Semi-private |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2474 | void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe, |
| 2475 | int64_t nLabel, |
| 2476 | TagSpecification TagSpec, |
| 2477 | UsefulBufC *pString) |
| 2478 | { |
| 2479 | QCBORItem Item; |
| 2480 | QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item); |
| 2481 | if(pMe->uLastError == QCBOR_SUCCESS) { |
| 2482 | *pString = Item.val.string; |
| 2483 | } |
| 2484 | } |
| 2485 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2486 | // Semi-private |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2487 | void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe, |
| 2488 | const char * szLabel, |
| 2489 | TagSpecification TagSpec, |
| 2490 | UsefulBufC *pString) |
| 2491 | { |
| 2492 | QCBORItem Item; |
| 2493 | QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item); |
| 2494 | if(pMe->uLastError == QCBOR_SUCCESS) { |
| 2495 | *pString = Item.val.string; |
| 2496 | } |
| 2497 | } |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2498 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2499 | /* |
| 2500 | Public function, see header qcbor/qcbor_decode.h file |
| 2501 | */ |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2502 | QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList) |
| 2503 | { |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2504 | return MapSearch(pCtx, pItemList, NULL, NULL, NULL); |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2505 | } |
| 2506 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2507 | /* |
| 2508 | Public function, see header qcbor/qcbor_decode.h file |
| 2509 | */ |
| 2510 | QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx, |
| 2511 | QCBORItem *pItemList, |
| 2512 | void *pCallbackCtx, |
| 2513 | QCBORItemCallback pfCB) |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2514 | { |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2515 | return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB); |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2516 | } |
| 2517 | |
| 2518 | |
Laurence Lundblade | 34691b9 | 2020-05-18 22:25:25 -0700 | [diff] [blame] | 2519 | static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[]) |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2520 | { |
Laurence Lundblade | 34691b9 | 2020-05-18 22:25:25 -0700 | [diff] [blame] | 2521 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 2522 | // Already in error state; do nothing. |
| 2523 | return; |
| 2524 | } |
| 2525 | |
| 2526 | size_t uOffset; |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2527 | pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL); |
Laurence Lundblade | 34691b9 | 2020-05-18 22:25:25 -0700 | [diff] [blame] | 2528 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 2529 | return; |
| 2530 | } |
| 2531 | |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 2532 | /* Need to get the current pre-order nesting level and cursor to be |
| 2533 | at the first item in the map/array just entered. |
| 2534 | |
| 2535 | Also need to current map nesting level and start cursor to |
| 2536 | be at the right place. |
| 2537 | |
| 2538 | The UsefulInBuf offset could be anywhere, so no assumption is |
| 2539 | made about it. |
| 2540 | |
| 2541 | No assumption is made about the pre-order nesting level either. |
| 2542 | |
| 2543 | However the map mode nesting level is assumed to be one above |
| 2544 | the map level that is being entered. |
| 2545 | */ |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2546 | /* Seek to the data item that is the map or array */ |
| 2547 | UsefulInputBuf_Seek(&(pMe->InBuf), uOffset); |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 2548 | pMe->nesting.pCurrent = pMe->nesting.pCurrentMap; // TODO: part of DecodeNesting |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2549 | |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 2550 | // TODO: check error? |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2551 | QCBORDecode_EnterBoundedMode(pMe, pSearch->uDataType); |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2552 | |
Laurence Lundblade | 34691b9 | 2020-05-18 22:25:25 -0700 | [diff] [blame] | 2553 | printdecode(pMe, "FinishEnter"); |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2554 | } |
| 2555 | |
| 2556 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2557 | /* |
| 2558 | Public function, see header qcbor/qcbor_decode.h file |
| 2559 | */ |
Laurence Lundblade | 34691b9 | 2020-05-18 22:25:25 -0700 | [diff] [blame] | 2560 | void QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel) |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2561 | { |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2562 | QCBORItem OneItemSeach[2]; |
| 2563 | OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64; |
| 2564 | OneItemSeach[0].label.int64 = nLabel; |
| 2565 | OneItemSeach[0].uDataType = QCBOR_TYPE_MAP; |
| 2566 | OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2567 | |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2568 | /* The map to enter was found, now finish of entering it. */ |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2569 | SearchAndEnter(pMe, OneItemSeach); |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2570 | } |
| 2571 | |
| 2572 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2573 | /* |
| 2574 | Public function, see header qcbor/qcbor_decode.h file |
| 2575 | */ |
Laurence Lundblade | 34691b9 | 2020-05-18 22:25:25 -0700 | [diff] [blame] | 2576 | void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel) |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2577 | { |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2578 | QCBORItem OneItemSeach[2]; |
| 2579 | OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING; |
| 2580 | OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel); |
| 2581 | OneItemSeach[0].uDataType = QCBOR_TYPE_MAP; |
| 2582 | OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2583 | |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2584 | SearchAndEnter(pMe, OneItemSeach); |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2585 | } |
| 2586 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2587 | /* |
| 2588 | Public function, see header qcbor/qcbor_decode.h file |
| 2589 | */ |
Laurence Lundblade | 34691b9 | 2020-05-18 22:25:25 -0700 | [diff] [blame] | 2590 | void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel) |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2591 | { |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2592 | QCBORItem OneItemSeach[2]; |
| 2593 | OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64; |
| 2594 | OneItemSeach[0].label.int64 = nLabel; |
| 2595 | OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY; |
| 2596 | OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2597 | |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2598 | SearchAndEnter(pMe, OneItemSeach); |
Laurence Lundblade | 34691b9 | 2020-05-18 22:25:25 -0700 | [diff] [blame] | 2599 | } |
| 2600 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2601 | /* |
| 2602 | Public function, see header qcbor/qcbor_decode.h file |
| 2603 | */ |
Laurence Lundblade | 34691b9 | 2020-05-18 22:25:25 -0700 | [diff] [blame] | 2604 | void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel) |
| 2605 | { |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2606 | QCBORItem OneItemSeach[2]; |
| 2607 | OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING; |
| 2608 | OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel); |
| 2609 | OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY; |
| 2610 | OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2611 | |
Laurence Lundblade | b90f536 | 2020-05-25 12:17:40 -0700 | [diff] [blame] | 2612 | SearchAndEnter(pMe, OneItemSeach); |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2613 | } |
| 2614 | |
| 2615 | |
| 2616 | |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2617 | /* Next item must be map or this generates an error */ |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2618 | void QCBORDecode_EnterBoundedMode(QCBORDecodeContext *pMe, uint8_t uType) |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2619 | { |
Laurence Lundblade | 34691b9 | 2020-05-18 22:25:25 -0700 | [diff] [blame] | 2620 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 2621 | // Already in error state; do nothing. |
| 2622 | return; |
| 2623 | } |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2624 | |
| 2625 | /* Get the data item that is the map that is being searched */ |
Laurence Lundblade | 34691b9 | 2020-05-18 22:25:25 -0700 | [diff] [blame] | 2626 | QCBORItem Item; |
Laurence Lundblade | 986017c | 2020-05-23 19:25:02 -0700 | [diff] [blame] | 2627 | pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item); |
Laurence Lundblade | 34691b9 | 2020-05-18 22:25:25 -0700 | [diff] [blame] | 2628 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 2629 | return; |
Laurence Lundblade | 3f9ef04 | 2020-04-14 13:15:51 -0700 | [diff] [blame] | 2630 | } |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 2631 | if(Item.uDataType != uType) { |
Laurence Lundblade | 34691b9 | 2020-05-18 22:25:25 -0700 | [diff] [blame] | 2632 | pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE; |
| 2633 | return; |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2634 | } |
| 2635 | |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2636 | DecodeNesting_EnterBoundedMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf))); |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2637 | |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2638 | // TODO: restrict input to less than this or some other invalidation strategy. |
| 2639 | pMe->uMapEndOffset = 0xffffffff; // Invalidate the cached map end. |
| 2640 | |
Laurence Lundblade | 34691b9 | 2020-05-18 22:25:25 -0700 | [diff] [blame] | 2641 | printdecode(pMe, "EnterMapModeDone"); |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2642 | } |
| 2643 | |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2644 | |
| 2645 | // Semi-private function |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2646 | void QCBORDecode_ExitBoundedMode(QCBORDecodeContext *pMe, uint8_t uType) |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2647 | { |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2648 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 2649 | // Already in error state; do nothing. |
| 2650 | return; |
| 2651 | } |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2652 | |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2653 | printdecode(pMe, "start exit"); |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2654 | |
| 2655 | QCBORError uErr = QCBOR_SUCCESS; |
| 2656 | |
| 2657 | if(!DecodeNesting_BoundedIsType(&(pMe->nesting), uType)){ |
| 2658 | uErr = QCBOR_ERR_CLOSE_MISMATCH; |
| 2659 | goto Done; |
| 2660 | } |
| 2661 | |
| 2662 | /* Have to set the offset to the end of the map/array |
| 2663 | that is being exited. If there is no cached value, |
| 2664 | from previous map search, then do a dummy search. */ |
| 2665 | if(pMe->uMapEndOffset == 0xffffffff) { |
| 2666 | QCBORItem Dummy; |
| 2667 | Dummy.uLabelType = QCBOR_TYPE_NONE; |
| 2668 | uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL); |
| 2669 | if(uErr != QCBOR_SUCCESS) { |
| 2670 | goto Done; |
| 2671 | } |
| 2672 | } |
| 2673 | UsefulInputBuf_Seek(&(pMe->InBuf), pMe->uMapEndOffset); |
| 2674 | pMe->uMapEndOffset = 0xffffffff; // Invalidate the cached map end. |
| 2675 | |
| 2676 | /* Before acending, mark this level as no longer in bound mode. */ |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2677 | pMe->nesting.pCurrentMap->uType &= ~QCBOR_NEST_TYPE_IS_BOUND; |
| 2678 | |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2679 | // Always go up one level |
| 2680 | // Need error check to know level is bounded mode and not at top level |
| 2681 | pMe->nesting.pCurrent = pMe->nesting.pCurrentMap - 1; // TODO error check |
| 2682 | |
| 2683 | uErr = Ascender(pMe); |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2684 | if(uErr != QCBOR_SUCCESS) { |
| 2685 | goto Done; |
| 2686 | } |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2687 | |
| 2688 | /* Also ascend to the next higest bounded mode level if |
| 2689 | there is one. */ |
| 2690 | while(1) { |
| 2691 | pMe->nesting.pCurrentMap--; |
| 2692 | if(DecodeNesting_InBoundedMode(&(pMe->nesting))) { |
| 2693 | break; |
| 2694 | } |
| 2695 | if(pMe->nesting.pCurrentMap == &(pMe->nesting.pMapsAndArrays[0])) { |
| 2696 | pMe->nesting.pCurrentMap = NULL; |
| 2697 | break; |
| 2698 | } |
| 2699 | } |
| 2700 | |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2701 | Done: |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2702 | printdecode(pMe, "end exit"); |
Laurence Lundblade | 2b843b5 | 2020-06-16 20:51:03 -0700 | [diff] [blame^] | 2703 | pMe->uLastError = (uint8_t)uErr; |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2704 | } |
| 2705 | |
| 2706 | |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2707 | void QCBORDecode_RewindMap(QCBORDecodeContext *pMe) |
Laurence Lundblade | bb87be2 | 2020-04-09 19:15:32 -0700 | [diff] [blame] | 2708 | { |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2709 | // TODO: check for map mode; test this |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2710 | pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount; |
| 2711 | UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset); |
| 2712 | } |
| 2713 | |
| 2714 | |
Laurence Lundblade | 1341c59 | 2020-04-11 14:19:05 -0700 | [diff] [blame] | 2715 | |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2716 | void QCBORDecode_EnterBstr(QCBORDecodeContext *pMe) |
| 2717 | { |
| 2718 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 2719 | // Already in error state; do nothing. |
| 2720 | return; |
| 2721 | } |
| 2722 | |
| 2723 | /* Get the data item that is the map that is being searched */ |
| 2724 | QCBORItem Item; |
| 2725 | pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item); |
| 2726 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 2727 | return; |
| 2728 | } |
| 2729 | if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) { |
| 2730 | pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE; |
| 2731 | return; |
| 2732 | } |
| 2733 | |
| 2734 | // TODO: check for tag 24 |
| 2735 | |
| 2736 | // Need to move UIB input cursor to the right place |
| 2737 | |
| 2738 | // Really this is a subtraction and an assignment; not much code |
| 2739 | // There is a range check in the seek. |
| 2740 | const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf)); |
| 2741 | |
| 2742 | UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset - Item.val.string.len); |
| 2743 | |
| 2744 | UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOffset); |
| 2745 | |
| 2746 | // TODO: comment on cast |
Laurence Lundblade | 0a042a9 | 2020-06-12 14:09:50 -0700 | [diff] [blame] | 2747 | pMe->uLastError = (uint8_t)DecodeNesting_Descend(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING, UINT16_MAX, (uint32_t)uEndOffset); |
Laurence Lundblade | 24d509a | 2020-06-06 18:43:15 -0700 | [diff] [blame] | 2748 | } |
| 2749 | |
| 2750 | |
Laurence Lundblade | d8c82c5 | 2020-06-12 22:15:52 -0700 | [diff] [blame] | 2751 | void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pBstr) |
| 2752 | { |
| 2753 | QCBORItem Item; |
| 2754 | QCBORDecode_GetNext(pMe, &Item); |
| 2755 | // Need to set UIB cursor to start of bstr and UIB length to end of bstr |
| 2756 | |
| 2757 | // TODO: combine with above |
| 2758 | |
| 2759 | } |
| 2760 | |
| 2761 | //void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pCtx, int64_t uLabel, UsefulBufC *pBstr); |
| 2762 | |
| 2763 | //void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, UsefulBufC *pBstr); |
| 2764 | |
| 2765 | void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pCtx) |
| 2766 | { |
| 2767 | // Need to set the cursor to end of the bstr and length to the next length |
| 2768 | // above in the nesting tree (or the top level length). |
| 2769 | |
| 2770 | } |
| 2771 | |
Laurence Lundblade | bf3c42d | 2020-04-14 19:08:51 -0700 | [diff] [blame] | 2772 | |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 2773 | |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2774 | |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2775 | |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2776 | |
Laurence Lundblade | 11a064e | 2020-05-07 13:13:42 -0700 | [diff] [blame] | 2777 | |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2778 | |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2779 | static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool) |
| 2780 | { |
| 2781 | switch(pItem->uDataType) { |
| 2782 | case QCBOR_TYPE_TRUE: |
| 2783 | *pBool = true; |
| 2784 | return QCBOR_SUCCESS; |
| 2785 | break; |
| 2786 | |
| 2787 | case QCBOR_TYPE_FALSE: |
| 2788 | *pBool = false; |
| 2789 | return QCBOR_SUCCESS; |
| 2790 | break; |
| 2791 | |
| 2792 | default: |
| 2793 | return QCBOR_ERR_UNEXPECTED_TYPE; |
| 2794 | break; |
| 2795 | } |
| 2796 | } |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 2797 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2798 | /* |
| 2799 | Public function, see header qcbor/qcbor_decode.h file |
| 2800 | */ |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2801 | void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue) |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 2802 | { |
Laurence Lundblade | bf3c42d | 2020-04-14 19:08:51 -0700 | [diff] [blame] | 2803 | if(pMe->uLastError != QCBOR_SUCCESS) { |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2804 | // Already in error state, do nothing |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 2805 | return; |
| 2806 | } |
| 2807 | |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2808 | QCBORError nError; |
| 2809 | QCBORItem Item; |
| 2810 | |
| 2811 | nError = QCBORDecode_GetNext(pMe, &Item); |
| 2812 | if(nError != QCBOR_SUCCESS) { |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2813 | pMe->uLastError = (uint8_t)nError; |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2814 | return; |
| 2815 | } |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2816 | pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue); |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 2817 | } |
| 2818 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2819 | /* |
| 2820 | Public function, see header qcbor/qcbor_decode.h file |
| 2821 | */ |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2822 | void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue) |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 2823 | { |
| 2824 | QCBORItem Item; |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2825 | QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item); |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 2826 | |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2827 | pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue); |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 2828 | } |
| 2829 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2830 | /* |
| 2831 | Public function, see header qcbor/qcbor_decode.h file |
| 2832 | */ |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2833 | void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue) |
| 2834 | { |
| 2835 | QCBORItem Item; |
| 2836 | QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item); |
| 2837 | |
| 2838 | pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue); |
| 2839 | } |
| 2840 | |
| 2841 | |
| 2842 | |
| 2843 | void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr) |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2844 | { |
Laurence Lundblade | bf3c42d | 2020-04-14 19:08:51 -0700 | [diff] [blame] | 2845 | if(pMe->uLastError != QCBOR_SUCCESS) { |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2846 | // Already in error state, do nothing |
| 2847 | return; |
| 2848 | } |
| 2849 | |
| 2850 | QCBORError nError; |
| 2851 | QCBORItem Item; |
| 2852 | |
| 2853 | nError = QCBORDecode_GetNext(pMe, &Item); |
| 2854 | if(nError != QCBOR_SUCCESS) { |
Laurence Lundblade | 82c2a8f | 2020-04-29 12:40:19 -0700 | [diff] [blame] | 2855 | pMe->uLastError = (uint8_t)nError; |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2856 | return; |
| 2857 | } |
| 2858 | |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2859 | pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType); |
| 2860 | |
| 2861 | if(pMe->uLastError == QCBOR_SUCCESS) { |
| 2862 | *pBstr = Item.val.string; |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2863 | } |
| 2864 | } |
| 2865 | |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2866 | |
| 2867 | |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2868 | |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 2869 | static QCBORError ConvertBigNum(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pValue, bool *pbIsNegative) |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2870 | { |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2871 | *pbIsNegative = false; |
| 2872 | |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 2873 | bool bMustBeTagged = true; // TODO: fix this --- they have to tell us if they are expecting positive or negative |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2874 | |
| 2875 | switch(pItem->uDataType) { |
| 2876 | case QCBOR_TYPE_BYTE_STRING: |
| 2877 | // TODO: check that there is no tag here? |
| 2878 | if(bMustBeTagged) { |
| 2879 | return QCBOR_ERR_UNEXPECTED_TYPE; |
| 2880 | } else { |
| 2881 | *pValue = pItem->val.string; |
| 2882 | return QCBOR_SUCCESS; |
| 2883 | } |
| 2884 | break; |
| 2885 | |
| 2886 | case QCBOR_TYPE_POSBIGNUM: |
| 2887 | *pValue = pItem->val.string; |
| 2888 | return QCBOR_SUCCESS; |
| 2889 | break; |
| 2890 | |
| 2891 | case QCBOR_TYPE_NEGBIGNUM: |
| 2892 | *pbIsNegative = true; |
| 2893 | *pValue = pItem->val.string; |
| 2894 | return QCBOR_SUCCESS; |
| 2895 | break; |
| 2896 | |
| 2897 | default: |
| 2898 | return QCBOR_ERR_UNEXPECTED_TYPE; |
| 2899 | break; |
| 2900 | } |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2901 | } |
| 2902 | |
| 2903 | |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 2904 | /* |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 2905 | @param[in] bMustBeTagged If \c true, then the data item must be tagged as either |
| 2906 | a positive or negative bignum. If \c false, then it only must be a byte string and bIsNegative |
| 2907 | will always be false on the asumption that it is positive, but it can be interpretted as |
| 2908 | negative if the the sign is know from other context. |
| 2909 | @param[out] pValue The bytes that make up the big num |
| 2910 | @param[out] pbIsNegative \c true if tagged as a negative big num. \c false otherwise. |
| 2911 | |
| 2912 | if bMustBeTagged is false, then this will succeed if the data item is a plain byte string, |
| 2913 | a positive big num or a negative big num. |
| 2914 | |
| 2915 | */ |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 2916 | void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative) |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 2917 | { |
| 2918 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 2919 | // Already in error state, do nothing |
| 2920 | return; |
| 2921 | } |
| 2922 | |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 2923 | QCBORItem Item; |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2924 | QCBORError uError = QCBORDecode_GetNext(pMe, &Item); |
| 2925 | if(uError != QCBOR_SUCCESS) { |
| 2926 | pMe->uLastError = (uint8_t)uError; |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 2927 | return; |
| 2928 | } |
| 2929 | |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 2930 | pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative); |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 2931 | } |
| 2932 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 2933 | /* |
| 2934 | Public function, see header qcbor/qcbor_decode.h file |
| 2935 | */ |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 2936 | void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative) |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2937 | { |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 2938 | QCBORItem Item; |
| 2939 | QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item); |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 2940 | |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 2941 | pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative); |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2942 | } |
| 2943 | |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 2944 | /* |
| 2945 | Public function, see header qcbor/qcbor_decode.h file |
| 2946 | */ |
| 2947 | void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative) |
| 2948 | { |
| 2949 | QCBORItem Item; |
| 2950 | QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item); |
| 2951 | |
| 2952 | pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative); |
| 2953 | } |
| 2954 | |
| 2955 | |
| 2956 | |
| 2957 | // Semi private |
| 2958 | QCBORError FarfMIME(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsNot7Bit) |
| 2959 | { |
| 2960 | const TagSpecification TagSpecText = {uTagRequirement, QCBOR_TYPE_MIME, {QCBOR_TYPE_TEXT_STRING, 0,0,0,0,0}}; |
| 2961 | const TagSpecification TagSpecBinary = {uTagRequirement, QCBOR_TYPE_BINARY_MIME, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}}; |
| 2962 | |
| 2963 | QCBORError uReturn; |
| 2964 | |
| 2965 | if(CheckTagRequirement(TagSpecText, pItem->uDataType)) { |
| 2966 | *pMessage = pItem->val.string; |
| 2967 | if(pbIsNot7Bit != NULL) { |
| 2968 | *pbIsNot7Bit = false; |
| 2969 | } |
| 2970 | uReturn = QCBOR_SUCCESS; |
| 2971 | } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType)) { |
| 2972 | *pMessage = pItem->val.string; |
| 2973 | if(pbIsNot7Bit != NULL) { |
| 2974 | *pbIsNot7Bit = true; |
| 2975 | } |
| 2976 | uReturn = QCBOR_SUCCESS; |
| 2977 | |
| 2978 | } else { |
| 2979 | uReturn = QCBOR_ERR_UNEXPECTED_TYPE; |
| 2980 | } |
| 2981 | |
| 2982 | return uReturn; |
| 2983 | } |
| 2984 | |
| 2985 | |
| 2986 | |
| 2987 | |
| 2988 | |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2989 | |
| 2990 | |
| 2991 | |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 2992 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 2993 | typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult); |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 2994 | |
| 2995 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 2996 | // The main exponentiator that works on only positive numbers |
Laurence Lundblade | 9ab5abb | 2020-05-20 12:10:45 -0700 | [diff] [blame] | 2997 | static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult) |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 2998 | { |
Laurence Lundblade | 9ab5abb | 2020-05-20 12:10:45 -0700 | [diff] [blame] | 2999 | uint64_t uResult = uMantissa; |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3000 | |
Laurence Lundblade | 9ab5abb | 2020-05-20 12:10:45 -0700 | [diff] [blame] | 3001 | if(uResult != 0) { |
| 3002 | /* This loop will run a maximum of 19 times because |
| 3003 | * UINT64_MAX < 10 ^^ 19. More than that will cause |
| 3004 | * exit with the overflow error |
| 3005 | */ |
| 3006 | for(; nExponent > 0; nExponent--) { |
| 3007 | if(uResult > UINT64_MAX / 10) { |
| 3008 | return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow |
| 3009 | } |
| 3010 | uResult = uResult * 10; |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3011 | } |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3012 | |
Laurence Lundblade | 9ab5abb | 2020-05-20 12:10:45 -0700 | [diff] [blame] | 3013 | for(; nExponent < 0; nExponent++) { |
| 3014 | uResult = uResult / 10; |
| 3015 | if(uResult == 0) { |
| 3016 | return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error |
| 3017 | } |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3018 | } |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3019 | } |
Laurence Lundblade | 9ab5abb | 2020-05-20 12:10:45 -0700 | [diff] [blame] | 3020 | /* else, mantissa is zero so this returns zero */ |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3021 | |
| 3022 | *puResult = uResult; |
| 3023 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3024 | return QCBOR_SUCCESS; |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3025 | } |
| 3026 | |
| 3027 | |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3028 | /* Convert a decimal fraction to an int64_t without using |
| 3029 | floating point or math libraries. Most decimal fractions |
| 3030 | will not fit in an int64_t and this will error out with |
| 3031 | under or overflow |
| 3032 | */ |
Laurence Lundblade | 9ab5abb | 2020-05-20 12:10:45 -0700 | [diff] [blame] | 3033 | static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult) |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3034 | { |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3035 | uint64_t uResult; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3036 | |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3037 | uResult = uMantissa; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3038 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3039 | /* This loop will run a maximum of 64 times because |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3040 | * INT64_MAX < 2^31. More than that will cause |
| 3041 | * exist with the overflow error |
| 3042 | */ |
| 3043 | while(nExponent > 0) { |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3044 | if(uResult > UINT64_MAX >> 1) { |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3045 | return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3046 | } |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3047 | uResult = uResult << 1; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3048 | nExponent--; |
| 3049 | } |
| 3050 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3051 | while(nExponent < 0 ) { |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3052 | if(uResult == 0) { |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3053 | return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error |
| 3054 | } |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3055 | uResult = uResult >> 1; |
Laurence Lundblade | 9ab5abb | 2020-05-20 12:10:45 -0700 | [diff] [blame] | 3056 | nExponent++; |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3057 | } |
| 3058 | |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3059 | *puResult = uResult; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3060 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3061 | return QCBOR_SUCCESS; |
| 3062 | } |
| 3063 | |
Laurence Lundblade | 9ab5abb | 2020-05-20 12:10:45 -0700 | [diff] [blame] | 3064 | /* |
| 3065 | Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator. |
| 3066 | */ |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3067 | static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp) |
| 3068 | { |
| 3069 | uint64_t uResult; |
| 3070 | |
Laurence Lundblade | 9ab5abb | 2020-05-20 12:10:45 -0700 | [diff] [blame] | 3071 | // Take the absolute value of the mantissa and convert to unsigned. |
| 3072 | // TODO: this should be possible in one intruction |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3073 | uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa; |
| 3074 | |
| 3075 | // Do the exponentiation of the positive mantissa |
| 3076 | QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult); |
| 3077 | if(uReturn) { |
| 3078 | return uReturn; |
| 3079 | } |
| 3080 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3081 | |
Laurence Lundblade | 983500d | 2020-05-14 11:49:34 -0700 | [diff] [blame] | 3082 | /* (uint64_t)INT64_MAX+1 is used to represent the absolute value |
| 3083 | of INT64_MIN. This assumes two's compliment representation where |
| 3084 | INT64_MIN is one increment farther from 0 than INT64_MAX. |
| 3085 | Trying to write -INT64_MIN doesn't work to get this because the |
| 3086 | compiler tries to work with an int64_t which can't represent |
| 3087 | -INT64_MIN. |
| 3088 | */ |
| 3089 | uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1; |
| 3090 | |
| 3091 | // Error out if too large |
| 3092 | if(uResult > uMax) { |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3093 | return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; |
| 3094 | } |
| 3095 | |
| 3096 | // Casts are safe because of checks above |
| 3097 | *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult; |
| 3098 | |
| 3099 | return QCBOR_SUCCESS; |
| 3100 | } |
| 3101 | |
Laurence Lundblade | 9ab5abb | 2020-05-20 12:10:45 -0700 | [diff] [blame] | 3102 | /* |
| 3103 | Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator. |
| 3104 | */ |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3105 | static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp) |
| 3106 | { |
| 3107 | if(nMantissa < 0) { |
| 3108 | return QCBOR_ERR_NUMBER_SIGN_CONVERSION; |
| 3109 | } |
| 3110 | |
| 3111 | // Cast to unsigned is OK because of check for negative |
| 3112 | // Cast to unsigned is OK because UINT64_MAX > INT64_MAX |
| 3113 | // Exponentiation is straight forward |
| 3114 | return (*pfExp)((uint64_t)nMantissa, nExponent, puResult); |
| 3115 | } |
| 3116 | |
| 3117 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3118 | #include <math.h> |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3119 | |
| 3120 | |
Laurence Lundblade | 9ab5abb | 2020-05-20 12:10:45 -0700 | [diff] [blame] | 3121 | static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult) |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3122 | { |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3123 | uint64_t uResult; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3124 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3125 | uResult = 0; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3126 | const uint8_t *pByte = BigNum.ptr; |
| 3127 | size_t uLen = BigNum.len; |
| 3128 | while(uLen--) { |
Laurence Lundblade | 313b286 | 2020-05-16 01:23:06 -0700 | [diff] [blame] | 3129 | if(uResult > (uMax >> 8)) { |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3130 | return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3131 | } |
Laurence Lundblade | 313b286 | 2020-05-16 01:23:06 -0700 | [diff] [blame] | 3132 | uResult = (uResult << 8) + *pByte++; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3133 | } |
| 3134 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3135 | *pResult = uResult; |
| 3136 | return QCBOR_SUCCESS; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3137 | } |
| 3138 | |
Laurence Lundblade | 887add8 | 2020-05-17 05:50:34 -0700 | [diff] [blame] | 3139 | static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult) |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3140 | { |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3141 | return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult); |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3142 | } |
| 3143 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3144 | static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult) |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3145 | { |
| 3146 | uint64_t uResult; |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3147 | QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult); |
| 3148 | if(uError) { |
| 3149 | return uError; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3150 | } |
| 3151 | /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */ |
| 3152 | *pResult = (int64_t)uResult; |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3153 | return QCBOR_SUCCESS; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3154 | } |
| 3155 | |
| 3156 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3157 | static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult) |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3158 | { |
| 3159 | uint64_t uResult; |
Laurence Lundblade | da09597 | 2020-06-06 18:35:33 -0700 | [diff] [blame] | 3160 | /* negaative int furthest from zero is INT64_MIN |
| 3161 | which is expressed as -INT64_MAX-1. The value of |
| 3162 | a negative bignum is -n-1, one further from zero |
| 3163 | than the positive bignum */ |
| 3164 | |
| 3165 | /* say INT64_MIN is -2; then INT64_MAX is 1. |
| 3166 | Then -n-1 <= INT64_MIN. |
| 3167 | Then -n -1 <= -INT64_MAX - 1 |
| 3168 | THen n <= INT64_MAX. */ |
| 3169 | QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult); |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3170 | if(uError) { |
| 3171 | return uError; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3172 | } |
| 3173 | /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */ |
Laurence Lundblade | 887add8 | 2020-05-17 05:50:34 -0700 | [diff] [blame] | 3174 | // TODO: this code is incorrect. See RFC 7049 |
Laurence Lundblade | da09597 | 2020-06-06 18:35:33 -0700 | [diff] [blame] | 3175 | uResult++; // this is the -1 in -n-1 |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3176 | *pResult = -(int64_t)uResult; |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3177 | return QCBOR_SUCCESS; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3178 | } |
| 3179 | |
Laurence Lundblade | f6c8666 | 2020-05-12 02:08:00 -0700 | [diff] [blame] | 3180 | #include "fenv.h" |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3181 | |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3182 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3183 | /* |
| 3184 | Convert a integers and floats to an int64_t. |
| 3185 | |
| 3186 | \param[in] uOptions Bit mask list of conversion options. |
| 3187 | |
| 3188 | \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions. |
| 3189 | |
| 3190 | \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted |
| 3191 | |
| 3192 | \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small. |
| 3193 | |
| 3194 | */ |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3195 | static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue) |
| 3196 | { |
| 3197 | switch(pItem->uDataType) { |
| 3198 | // TODO: float when ifdefs are set |
| 3199 | case QCBOR_TYPE_DOUBLE: |
| 3200 | if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) { |
| 3201 | // TODO: what about under/overflow here? |
| 3202 | // Invokes the floating-point HW and/or compiler-added libraries |
| 3203 | feclearexcept(FE_ALL_EXCEPT); |
| 3204 | *pnValue = llround(pItem->val.dfnum); |
| 3205 | if(fetestexcept(FE_INVALID)) { |
| 3206 | // TODO: better error code |
| 3207 | return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; |
| 3208 | } |
| 3209 | } else { |
| 3210 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3211 | } |
| 3212 | break; |
| 3213 | |
| 3214 | case QCBOR_TYPE_INT64: |
| 3215 | if(uOptions & QCBOR_CONVERT_TYPE_INT64) { |
| 3216 | *pnValue = pItem->val.int64; |
| 3217 | } else { |
| 3218 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3219 | } |
| 3220 | break; |
| 3221 | |
| 3222 | case QCBOR_TYPE_UINT64: |
| 3223 | if(uOptions & QCBOR_CONVERT_TYPE_UINT64) { |
| 3224 | if(pItem->val.uint64 < INT64_MAX) { |
| 3225 | *pnValue = pItem->val.int64; |
| 3226 | } else { |
| 3227 | return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; |
| 3228 | } |
| 3229 | } else { |
| 3230 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3231 | } |
| 3232 | break; |
| 3233 | |
| 3234 | default: |
| 3235 | return QCBOR_ERR_UNEXPECTED_TYPE; |
| 3236 | } |
| 3237 | return QCBOR_SUCCESS; |
| 3238 | } |
| 3239 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3240 | |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3241 | void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe, |
| 3242 | uint32_t uOptions, |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3243 | int64_t *pnValue, |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3244 | QCBORItem *pItem) |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3245 | { |
Laurence Lundblade | bf3c42d | 2020-04-14 19:08:51 -0700 | [diff] [blame] | 3246 | if(pMe->uLastError != QCBOR_SUCCESS) { |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3247 | return; |
| 3248 | } |
| 3249 | |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3250 | QCBORItem Item; |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3251 | QCBORError uError = QCBORDecode_GetNext(pMe, &Item); |
| 3252 | if(uError) { |
| 3253 | pMe->uLastError = (uint8_t)uError; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3254 | return; |
| 3255 | } |
| 3256 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3257 | if(pItem) { |
| 3258 | *pItem = Item; |
| 3259 | } |
| 3260 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3261 | pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue); |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3262 | } |
| 3263 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3264 | |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3265 | void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe, |
| 3266 | int64_t nLabel, |
| 3267 | uint32_t uOptions, |
| 3268 | int64_t *pnValue, |
| 3269 | QCBORItem *pItem) |
| 3270 | { |
| 3271 | QCBORItem Item; |
| 3272 | QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item); |
| 3273 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3274 | pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue); |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3275 | } |
| 3276 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3277 | |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3278 | void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe, |
| 3279 | const char * szLabel, |
| 3280 | uint32_t uOptions, |
| 3281 | int64_t *pnValue, |
| 3282 | QCBORItem *pItem) |
| 3283 | { |
| 3284 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 3285 | return; |
| 3286 | } |
| 3287 | |
| 3288 | QCBORItem Item; |
| 3289 | QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item); |
| 3290 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3291 | pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue); |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3292 | } |
| 3293 | |
| 3294 | |
| 3295 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3296 | /* |
| 3297 | Convert a large variety of integer types to an int64_t. |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3298 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3299 | \param[in] uOptions Bit mask list of conversion options. |
| 3300 | |
| 3301 | \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions. |
| 3302 | |
| 3303 | \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted |
| 3304 | |
| 3305 | \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small. |
| 3306 | |
| 3307 | */ |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3308 | static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue) |
| 3309 | { |
| 3310 | QCBORError uErr; |
| 3311 | |
| 3312 | switch(pItem->uDataType) { |
| 3313 | |
| 3314 | case QCBOR_TYPE_POSBIGNUM: |
| 3315 | if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) { |
| 3316 | return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue); |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3317 | } else { |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3318 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3319 | } |
| 3320 | break; |
| 3321 | |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3322 | case QCBOR_TYPE_NEGBIGNUM: |
| 3323 | if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) { |
| 3324 | return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue); |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3325 | } else { |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3326 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3327 | } |
| 3328 | break; |
| 3329 | |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3330 | #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA |
| 3331 | case QCBOR_TYPE_DECIMAL_FRACTION: |
| 3332 | if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) { |
| 3333 | return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt, |
| 3334 | pItem->val.expAndMantissa.nExponent, |
| 3335 | pnValue, |
| 3336 | &Exponentitate10); |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3337 | } else { |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3338 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3339 | } |
| 3340 | break; |
| 3341 | |
| 3342 | case QCBOR_TYPE_BIGFLOAT: |
| 3343 | if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) { |
| 3344 | return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt, |
| 3345 | pItem->val.expAndMantissa.nExponent, |
| 3346 | pnValue, |
| 3347 | Exponentitate2); |
| 3348 | } else { |
| 3349 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3350 | } |
| 3351 | break; |
| 3352 | |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3353 | case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM: |
| 3354 | if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) { |
| 3355 | int64_t nMantissa; |
| 3356 | uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa); |
| 3357 | if(uErr) { |
| 3358 | return uErr; |
| 3359 | } |
| 3360 | return ExponentiateNN(nMantissa, |
| 3361 | pItem->val.expAndMantissa.nExponent, |
| 3362 | pnValue, |
| 3363 | Exponentitate10); |
| 3364 | } else { |
| 3365 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3366 | } |
| 3367 | break; |
| 3368 | |
| 3369 | case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM: |
| 3370 | if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) { |
| 3371 | int64_t nMantissa; |
| 3372 | uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa); |
| 3373 | if(uErr) { |
| 3374 | return uErr; |
| 3375 | } |
| 3376 | return ExponentiateNN(nMantissa, |
| 3377 | pItem->val.expAndMantissa.nExponent, |
| 3378 | pnValue, |
| 3379 | Exponentitate10); |
| 3380 | } else { |
| 3381 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3382 | } |
| 3383 | break; |
| 3384 | |
| 3385 | case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM: |
| 3386 | if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) { |
| 3387 | int64_t nMantissa; |
| 3388 | uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa); |
| 3389 | if(uErr) { |
| 3390 | return uErr; |
| 3391 | } |
| 3392 | return ExponentiateNN(nMantissa, |
| 3393 | pItem->val.expAndMantissa.nExponent, |
| 3394 | pnValue, |
| 3395 | Exponentitate2); |
| 3396 | } else { |
| 3397 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3398 | } |
| 3399 | break; |
| 3400 | |
| 3401 | case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM: |
| 3402 | if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) { |
| 3403 | int64_t nMantissa; |
| 3404 | uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa); |
| 3405 | if(uErr) { |
| 3406 | return uErr; |
| 3407 | } |
| 3408 | return ExponentiateNN(nMantissa, |
| 3409 | pItem->val.expAndMantissa.nExponent, |
| 3410 | pnValue, |
| 3411 | Exponentitate2); |
| 3412 | } else { |
| 3413 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3414 | } |
| 3415 | break; |
| 3416 | |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3417 | default: |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3418 | return QCBOR_ERR_UNEXPECTED_TYPE; |
| 3419 | #endif |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3420 | } |
| 3421 | } |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3422 | |
| 3423 | |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3424 | /* |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3425 | Public function, see header qcbor/qcbor_decode.h file |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3426 | */ |
| 3427 | void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue) |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3428 | { |
| 3429 | QCBORItem Item; |
| 3430 | |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3431 | QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item); |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3432 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3433 | if(pMe->uLastError == QCBOR_SUCCESS) { |
| 3434 | // The above conversion succeeded |
| 3435 | return; |
| 3436 | } |
| 3437 | |
Laurence Lundblade | f6c8666 | 2020-05-12 02:08:00 -0700 | [diff] [blame] | 3438 | if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) { |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3439 | // The above conversion failed in a way that code below can't correct |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3440 | return; |
| 3441 | } |
| 3442 | |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3443 | pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue); |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3444 | } |
| 3445 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3446 | |
| 3447 | /* |
| 3448 | Public function, see header qcbor/qcbor_decode.h file |
| 3449 | */ |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3450 | void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue) |
| 3451 | { |
| 3452 | QCBORItem Item; |
| 3453 | |
| 3454 | QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item); |
| 3455 | |
| 3456 | if(pMe->uLastError == QCBOR_SUCCESS) { |
| 3457 | // The above conversion succeeded |
| 3458 | return; |
| 3459 | } |
| 3460 | |
| 3461 | if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) { |
| 3462 | // The above conversion failed in a way that code below can't correct |
| 3463 | return; |
| 3464 | } |
| 3465 | |
| 3466 | pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue); |
| 3467 | } |
| 3468 | |
| 3469 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3470 | /* |
| 3471 | Public function, see header qcbor/qcbor_decode.h file |
| 3472 | */ |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3473 | void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue) |
| 3474 | { |
| 3475 | QCBORItem Item; |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3476 | QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item); |
| 3477 | |
| 3478 | if(pMe->uLastError == QCBOR_SUCCESS) { |
| 3479 | // The above conversion succeeded |
| 3480 | return; |
| 3481 | } |
| 3482 | |
| 3483 | if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) { |
| 3484 | // The above conversion failed in a way that code below can't correct |
| 3485 | return; |
| 3486 | } |
| 3487 | |
| 3488 | pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue); |
| 3489 | } |
| 3490 | |
| 3491 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3492 | static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue) |
| 3493 | { |
| 3494 | switch(pItem->uDataType) { |
| 3495 | // TODO: type flaot |
| 3496 | case QCBOR_TYPE_DOUBLE: |
| 3497 | if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) { |
| 3498 | feclearexcept(FE_ALL_EXCEPT); |
| 3499 | double dRounded = round(pItem->val.dfnum); |
| 3500 | // TODO: over/underflow |
| 3501 | if(fetestexcept(FE_INVALID)) { |
| 3502 | // TODO: better error code |
| 3503 | return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; |
| 3504 | } else if(isnan(dRounded)) { |
| 3505 | // TODO: better error code |
| 3506 | return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; |
| 3507 | } else if(dRounded >= 0) { |
| 3508 | *puValue = (uint64_t)dRounded; |
| 3509 | } else { |
| 3510 | return QCBOR_ERR_NUMBER_SIGN_CONVERSION; |
| 3511 | } |
| 3512 | } else { |
| 3513 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3514 | } |
| 3515 | break; |
Laurence Lundblade | 843a10c | 2020-05-23 13:57:00 -0700 | [diff] [blame] | 3516 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3517 | case QCBOR_TYPE_INT64: |
| 3518 | if(uOptions & QCBOR_CONVERT_TYPE_INT64) { |
| 3519 | if(pItem->val.int64 >= 0) { |
| 3520 | *puValue = (uint64_t)pItem->val.int64; |
| 3521 | } else { |
| 3522 | return QCBOR_ERR_NUMBER_SIGN_CONVERSION; |
| 3523 | } |
| 3524 | } else { |
| 3525 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3526 | } |
| 3527 | break; |
| 3528 | |
| 3529 | case QCBOR_TYPE_UINT64: |
| 3530 | if(uOptions & QCBOR_CONVERT_TYPE_UINT64) { |
| 3531 | *puValue = pItem->val.uint64; |
| 3532 | } else { |
| 3533 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3534 | } |
| 3535 | break; |
| 3536 | |
| 3537 | default: |
| 3538 | return QCBOR_ERR_UNEXPECTED_TYPE; |
| 3539 | } |
| 3540 | return QCBOR_SUCCESS; |
| 3541 | } |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3542 | |
| 3543 | |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3544 | void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe, |
| 3545 | uint32_t uOptions, |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3546 | uint64_t *puValue, |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3547 | QCBORItem *pItem) |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3548 | { |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3549 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 3550 | return; |
| 3551 | } |
| 3552 | |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3553 | QCBORItem Item; |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3554 | |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3555 | QCBORError uError = QCBORDecode_GetNext(pMe, &Item); |
| 3556 | if(uError) { |
| 3557 | pMe->uLastError = (uint8_t)uError; |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3558 | return; |
| 3559 | } |
| 3560 | |
Laurence Lundblade | a826c50 | 2020-05-10 21:07:00 -0700 | [diff] [blame] | 3561 | if(pItem) { |
| 3562 | *pItem = Item; |
| 3563 | } |
| 3564 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3565 | pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue); |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3566 | } |
| 3567 | |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3568 | |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 3569 | void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem) |
| 3570 | { |
| 3571 | int64_t uValue; |
| 3572 | QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, &uValue, pItem); |
| 3573 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 3574 | return; |
| 3575 | } |
| 3576 | |
| 3577 | if(QCBOR_Int64ToInt8(uValue, pnValue)) { |
| 3578 | pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; |
| 3579 | } |
| 3580 | } |
| 3581 | |
| 3582 | void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem) |
| 3583 | { |
| 3584 | int64_t uValue; |
| 3585 | QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, &uValue, pItem); |
| 3586 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 3587 | return; |
| 3588 | } |
| 3589 | |
| 3590 | if(QCBOR_Int64ToInt8(uValue, pnValue)) { |
| 3591 | pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; |
| 3592 | } |
| 3593 | } |
| 3594 | |
| 3595 | void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem) |
| 3596 | { |
| 3597 | int64_t uValue; |
| 3598 | QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, &uValue, pItem); |
| 3599 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 3600 | return; |
| 3601 | } |
| 3602 | |
| 3603 | if(QCBOR_Int64ToInt8(uValue, pnValue)) { |
| 3604 | pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; |
| 3605 | } |
| 3606 | } |
| 3607 | |
| 3608 | |
| 3609 | |
| 3610 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3611 | void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe, |
| 3612 | int64_t nLabel, |
| 3613 | uint32_t uOptions, |
| 3614 | uint64_t *puValue, |
| 3615 | QCBORItem *pItem) |
| 3616 | { |
| 3617 | QCBORItem Item; |
| 3618 | QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item); |
| 3619 | |
| 3620 | pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue); |
| 3621 | } |
| 3622 | |
| 3623 | |
| 3624 | void QCBORDecode_GetUint64ConvertInternalInMapSZ(QCBORDecodeContext *pMe, |
| 3625 | const char * szLabel, |
| 3626 | uint32_t uOptions, |
| 3627 | uint64_t *puValue, |
| 3628 | QCBORItem *pItem) |
| 3629 | { |
| 3630 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 3631 | return; |
| 3632 | } |
| 3633 | |
| 3634 | QCBORItem Item; |
| 3635 | QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item); |
| 3636 | |
| 3637 | pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue); |
| 3638 | } |
| 3639 | |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3640 | /* |
| 3641 | Public function, see header qcbor/qcbor_decode.h file |
| 3642 | */ |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3643 | static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue) |
| 3644 | { |
| 3645 | QCBORError uErr; |
| 3646 | |
| 3647 | switch(pItem->uDataType) { |
| 3648 | |
| 3649 | case QCBOR_TYPE_POSBIGNUM: |
| 3650 | if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) { |
| 3651 | return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue); |
| 3652 | } else { |
| 3653 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3654 | } |
| 3655 | break; |
| 3656 | |
| 3657 | case QCBOR_TYPE_NEGBIGNUM: |
| 3658 | if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) { |
| 3659 | return QCBOR_ERR_NUMBER_SIGN_CONVERSION; |
| 3660 | } else { |
| 3661 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3662 | } |
| 3663 | break; |
| 3664 | |
| 3665 | #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA |
| 3666 | |
| 3667 | case QCBOR_TYPE_DECIMAL_FRACTION: |
| 3668 | if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) { |
| 3669 | return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt, |
| 3670 | pItem->val.expAndMantissa.nExponent, |
| 3671 | puValue, |
| 3672 | Exponentitate10); |
| 3673 | } else { |
| 3674 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3675 | } |
| 3676 | break; |
| 3677 | |
| 3678 | case QCBOR_TYPE_BIGFLOAT: |
| 3679 | if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) { |
| 3680 | return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt, |
| 3681 | pItem->val.expAndMantissa.nExponent, |
| 3682 | puValue, |
| 3683 | Exponentitate2); |
| 3684 | } else { |
| 3685 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3686 | } |
| 3687 | break; |
| 3688 | |
| 3689 | case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM: |
| 3690 | if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) { |
| 3691 | // TODO: Would be better to convert to unsigned |
| 3692 | int64_t nMantissa; |
| 3693 | uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa); |
| 3694 | if(uErr != QCBOR_SUCCESS) { |
| 3695 | return uErr; |
| 3696 | } |
| 3697 | return ExponentitateNU(nMantissa, |
| 3698 | pItem->val.expAndMantissa.nExponent, |
| 3699 | puValue, |
| 3700 | Exponentitate10); |
| 3701 | } else { |
| 3702 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3703 | } |
| 3704 | break; |
| 3705 | |
| 3706 | case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM: |
| 3707 | if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) { |
| 3708 | return QCBOR_ERR_NUMBER_SIGN_CONVERSION; |
| 3709 | } else { |
| 3710 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3711 | } |
| 3712 | break; |
| 3713 | |
| 3714 | case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM: |
| 3715 | if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) { |
| 3716 | // TODO: Would be better to convert to unsigned |
| 3717 | int64_t nMantissa; |
| 3718 | uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa); |
| 3719 | if(uErr != QCBOR_SUCCESS) { |
| 3720 | return uErr; |
| 3721 | } |
| 3722 | return ExponentitateNU(nMantissa, |
| 3723 | pItem->val.expAndMantissa.nExponent, |
| 3724 | puValue, |
| 3725 | Exponentitate2); |
| 3726 | } else { |
| 3727 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3728 | } |
| 3729 | break; |
| 3730 | |
| 3731 | case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM: |
| 3732 | if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) { |
| 3733 | return QCBOR_ERR_NUMBER_SIGN_CONVERSION; |
| 3734 | } else { |
| 3735 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3736 | } |
| 3737 | break; |
| 3738 | #endif |
| 3739 | default: |
| 3740 | return QCBOR_ERR_UNEXPECTED_TYPE; |
| 3741 | } |
| 3742 | } |
| 3743 | |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 3744 | /* |
| 3745 | Public function, see header qcbor/qcbor_decode.h file |
| 3746 | */ |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3747 | void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue) |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3748 | { |
| 3749 | QCBORItem Item; |
| 3750 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3751 | QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item); |
Laurence Lundblade | 9c905e8 | 2020-04-25 11:31:38 -0700 | [diff] [blame] | 3752 | |
Laurence Lundblade | f6c8666 | 2020-05-12 02:08:00 -0700 | [diff] [blame] | 3753 | if(pMe->uLastError == QCBOR_SUCCESS) { |
| 3754 | // The above conversion succeeded |
| 3755 | return; |
| 3756 | } |
| 3757 | |
| 3758 | if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) { |
| 3759 | // The above conversion failed in a way that code below can't correct |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3760 | return; |
| 3761 | } |
| 3762 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3763 | pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue); |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3764 | } |
| 3765 | |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3766 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3767 | /* |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 3768 | Public function, see header qcbor/qcbor_decode.h file |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3769 | */ |
| 3770 | void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue) |
| 3771 | { |
| 3772 | QCBORItem Item; |
| 3773 | |
| 3774 | QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item); |
| 3775 | |
| 3776 | if(pMe->uLastError == QCBOR_SUCCESS) { |
| 3777 | // The above conversion succeeded |
| 3778 | return; |
| 3779 | } |
| 3780 | |
| 3781 | if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) { |
| 3782 | // The above conversion failed in a way that code below can't correct |
| 3783 | return; |
| 3784 | } |
| 3785 | |
| 3786 | pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue); |
| 3787 | } |
| 3788 | |
| 3789 | |
| 3790 | /* |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 3791 | Public function, see header qcbor/qcbor_decode.h file |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3792 | */ |
| 3793 | void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue) |
| 3794 | { |
| 3795 | QCBORItem Item; |
| 3796 | QCBORDecode_GetUint64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item); |
| 3797 | |
| 3798 | if(pMe->uLastError == QCBOR_SUCCESS) { |
| 3799 | // The above conversion succeeded |
| 3800 | return; |
| 3801 | } |
| 3802 | |
| 3803 | if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) { |
| 3804 | // The above conversion failed in a way that code below can't correct |
| 3805 | return; |
| 3806 | } |
| 3807 | |
| 3808 | pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue); |
| 3809 | } |
| 3810 | |
| 3811 | |
| 3812 | static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue) |
| 3813 | { |
| 3814 | switch(pItem->uDataType) { |
| 3815 | // TODO: float when ifdefs are set |
| 3816 | case QCBOR_TYPE_DOUBLE: |
| 3817 | if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) { |
| 3818 | if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) { |
| 3819 | *pdValue = pItem->val.dfnum; |
| 3820 | } else { |
| 3821 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3822 | } |
| 3823 | } |
| 3824 | break; |
| 3825 | |
| 3826 | case QCBOR_TYPE_INT64: |
| 3827 | if(uOptions & QCBOR_CONVERT_TYPE_INT64) { |
| 3828 | // TODO: how does this work? |
| 3829 | *pdValue = (double)pItem->val.int64; |
| 3830 | |
| 3831 | } else { |
| 3832 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3833 | } |
| 3834 | break; |
| 3835 | |
| 3836 | case QCBOR_TYPE_UINT64: |
| 3837 | if(uOptions & QCBOR_CONVERT_TYPE_UINT64) { |
| 3838 | *pdValue = (double)pItem->val.uint64; |
| 3839 | } else { |
| 3840 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3841 | } |
| 3842 | break; |
| 3843 | |
| 3844 | default: |
| 3845 | return QCBOR_ERR_UNEXPECTED_TYPE; |
| 3846 | } |
| 3847 | |
| 3848 | return QCBOR_SUCCESS; |
| 3849 | } |
| 3850 | |
| 3851 | |
| 3852 | |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3853 | void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe, |
| 3854 | uint32_t uOptions, |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3855 | double *pdValue, |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3856 | QCBORItem *pItem) |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 3857 | { |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 3858 | if(pMe->uLastError != QCBOR_SUCCESS) { |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3859 | return; |
| 3860 | } |
| 3861 | |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 3862 | QCBORItem Item; |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 3863 | |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3864 | QCBORError uError = QCBORDecode_GetNext(pMe, &Item); |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 3865 | if(uError) { |
| 3866 | pMe->uLastError = (uint8_t)uError; |
| 3867 | return; |
| 3868 | } |
| 3869 | |
| 3870 | if(pItem) { |
| 3871 | *pItem = Item; |
| 3872 | } |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3873 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3874 | pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue); |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 3875 | } |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3876 | |
Laurence Lundblade | c453744 | 2020-04-14 18:53:22 -0700 | [diff] [blame] | 3877 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3878 | void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe, |
| 3879 | int64_t nLabel, |
| 3880 | uint32_t uOptions, |
| 3881 | double *pdValue, |
| 3882 | QCBORItem *pItem) |
| 3883 | { |
| 3884 | QCBORItem Item; |
| 3885 | QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item); |
| 3886 | |
| 3887 | pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue); |
| 3888 | } |
| 3889 | |
| 3890 | void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe, |
| 3891 | const char * szLabel, |
| 3892 | uint32_t uOptions, |
| 3893 | double *pdValue, |
| 3894 | QCBORItem *pItem) |
| 3895 | { |
| 3896 | if(pMe->uLastError != QCBOR_SUCCESS) { |
| 3897 | return; |
| 3898 | } |
| 3899 | |
| 3900 | QCBORItem Item; |
| 3901 | QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item); |
| 3902 | |
| 3903 | pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue); |
| 3904 | } |
| 3905 | |
| 3906 | |
| 3907 | |
Laurence Lundblade | 9ab5abb | 2020-05-20 12:10:45 -0700 | [diff] [blame] | 3908 | static double ConvertBigNumToDouble(const UsefulBufC BigNum) |
| 3909 | { |
| 3910 | double dResult; |
| 3911 | |
| 3912 | dResult = 0.0; |
| 3913 | const uint8_t *pByte = BigNum.ptr; |
| 3914 | size_t uLen = BigNum.len; |
| 3915 | /* This will overflow and become the float value INFINITY if the number |
| 3916 | is too large to fit. No error will be logged. |
| 3917 | TODO: should an error be logged? */ |
| 3918 | while(uLen--) { |
| 3919 | dResult = (dResult * 256.0) + (double)*pByte++; |
| 3920 | } |
| 3921 | |
| 3922 | return dResult; |
| 3923 | } |
| 3924 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3925 | static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue) |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 3926 | { |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3927 | /* |
Laurence Lundblade | 54cd99c | 2020-05-15 02:25:32 -0700 | [diff] [blame] | 3928 | https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html |
| 3929 | |
| 3930 | */ |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3931 | switch(pItem->uDataType) { |
| 3932 | // TODO: type float |
| 3933 | case QCBOR_TYPE_DECIMAL_FRACTION: |
| 3934 | if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) { |
| 3935 | // TODO: rounding and overflow errors |
| 3936 | *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt * |
| 3937 | pow(10.0, (double)pItem->val.expAndMantissa.nExponent); |
| 3938 | } else { |
| 3939 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3940 | } |
| 3941 | break; |
| 3942 | |
| 3943 | case QCBOR_TYPE_BIGFLOAT: |
| 3944 | if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) { |
| 3945 | *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt * |
| 3946 | exp2((double)pItem->val.expAndMantissa.nExponent); |
| 3947 | } else { |
| 3948 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3949 | } |
| 3950 | break; |
| 3951 | |
| 3952 | case QCBOR_TYPE_POSBIGNUM: |
| 3953 | if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) { |
| 3954 | *pdValue = ConvertBigNumToDouble(pItem->val.bigNum); |
| 3955 | } else { |
| 3956 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3957 | } |
| 3958 | break; |
| 3959 | |
| 3960 | case QCBOR_TYPE_NEGBIGNUM: |
| 3961 | if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) { |
Laurence Lundblade | da09597 | 2020-06-06 18:35:33 -0700 | [diff] [blame] | 3962 | *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum); |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3963 | } else { |
| 3964 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3965 | } |
| 3966 | break; |
| 3967 | |
| 3968 | case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM: |
| 3969 | if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) { |
| 3970 | double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum); |
| 3971 | *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent); |
| 3972 | } else { |
| 3973 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3974 | } |
| 3975 | break; |
| 3976 | |
| 3977 | case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM: |
| 3978 | if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) { |
| 3979 | double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum); |
| 3980 | *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent); |
| 3981 | } else { |
| 3982 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3983 | } |
| 3984 | break; |
| 3985 | |
| 3986 | case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM: |
| 3987 | if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) { |
| 3988 | double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum); |
| 3989 | *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent); |
| 3990 | } else { |
| 3991 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 3992 | } |
| 3993 | break; |
| 3994 | |
| 3995 | case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM: |
| 3996 | if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) { |
Laurence Lundblade | da09597 | 2020-06-06 18:35:33 -0700 | [diff] [blame] | 3997 | double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum); |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 3998 | *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent); |
| 3999 | } else { |
| 4000 | return QCBOR_ERR_CONVERSION_NOT_REQUESTED; |
| 4001 | } |
| 4002 | break; |
| 4003 | |
| 4004 | default: |
| 4005 | return QCBOR_ERR_UNEXPECTED_TYPE; |
| 4006 | } |
| 4007 | |
| 4008 | return QCBOR_SUCCESS; |
| 4009 | } |
| 4010 | |
| 4011 | |
| 4012 | /* |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 4013 | Public function, see header qcbor/qcbor_decode.h file |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 4014 | */ |
| 4015 | void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue) |
| 4016 | { |
| 4017 | |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 4018 | QCBORItem Item; |
| 4019 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 4020 | QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item); |
Laurence Lundblade | b340ba7 | 2020-05-14 11:41:10 -0700 | [diff] [blame] | 4021 | |
| 4022 | if(pMe->uLastError == QCBOR_SUCCESS) { |
| 4023 | // The above conversion succeeded |
| 4024 | return; |
| 4025 | } |
| 4026 | |
| 4027 | if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) { |
| 4028 | // The above conversion failed in a way that code below can't correct |
| 4029 | return; |
| 4030 | } |
| 4031 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 4032 | pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue); |
Laurence Lundblade | e643064 | 2020-03-14 21:15:44 -0700 | [diff] [blame] | 4033 | } |
| 4034 | |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 4035 | |
| 4036 | /* |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 4037 | Public function, see header qcbor/qcbor_decode.h file |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 4038 | */ |
| 4039 | void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue) |
| 4040 | { |
| 4041 | QCBORItem Item; |
| 4042 | |
| 4043 | QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item); |
| 4044 | |
| 4045 | if(pMe->uLastError == QCBOR_SUCCESS) { |
| 4046 | // The above conversion succeeded |
| 4047 | return; |
| 4048 | } |
| 4049 | |
| 4050 | if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) { |
| 4051 | // The above conversion failed in a way that code below can't correct |
| 4052 | return; |
| 4053 | } |
| 4054 | |
| 4055 | pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue); |
| 4056 | } |
| 4057 | |
| 4058 | |
| 4059 | /* |
Laurence Lundblade | 4e2da00 | 2020-06-13 23:08:31 -0700 | [diff] [blame] | 4060 | Public function, see header qcbor/qcbor_decode.h file |
Laurence Lundblade | 7e5be1d | 2020-05-24 21:17:28 -0700 | [diff] [blame] | 4061 | */ |
| 4062 | void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue) |
| 4063 | { |
| 4064 | QCBORItem Item; |
| 4065 | QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item); |
| 4066 | |
| 4067 | if(pMe->uLastError == QCBOR_SUCCESS) { |
| 4068 | // The above conversion succeeded |
| 4069 | return; |
| 4070 | } |
| 4071 | |
| 4072 | if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) { |
| 4073 | // The above conversion failed in a way that code below can't correct |
| 4074 | return; |
| 4075 | } |
| 4076 | |
| 4077 | pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue); |
| 4078 | } |
Laurence Lundblade | 91853ae | 2020-06-15 19:35:58 -0700 | [diff] [blame] | 4079 | |
| 4080 | |
| 4081 | void FarfDecimalFraction(QCBORDecodeContext *pMe, |
| 4082 | uint8_t uTagRequirement, |
| 4083 | QCBORItem *pItem, |
| 4084 | int64_t *pnMantissa, |
| 4085 | int64_t *pnExponent) |
| 4086 | { |
| 4087 | QCBORError uErr; |
| 4088 | |
| 4089 | if(pItem->uDataType == QCBOR_TYPE_ARRAY) { |
| 4090 | if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) { |
| 4091 | pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE; |
| 4092 | return; |
| 4093 | } |
| 4094 | uErr = QCBORDecode_MantissaAndExponent(pMe, pItem); |
| 4095 | if(uErr != QCBOR_SUCCESS) { |
| 4096 | pMe->uLastError = (uint8_t)uErr; |
| 4097 | return; |
| 4098 | } |
| 4099 | } |
| 4100 | |
| 4101 | if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) { |
| 4102 | pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE; |
| 4103 | return; |
| 4104 | } |
| 4105 | |
| 4106 | switch (pItem->uDataType) { |
| 4107 | |
| 4108 | case QCBOR_TYPE_DECIMAL_FRACTION: |
| 4109 | *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt; |
| 4110 | *pnExponent = pItem->val.expAndMantissa.nExponent; |
| 4111 | break; |
| 4112 | |
| 4113 | case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM: |
| 4114 | *pnExponent = pItem->val.expAndMantissa.nExponent; |
| 4115 | |
| 4116 | uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa); |
| 4117 | if(uErr != QCBOR_SUCCESS) { |
| 4118 | pMe->uLastError = (uint8_t)uErr; |
| 4119 | } |
| 4120 | break; |
| 4121 | |
| 4122 | case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM: |
| 4123 | *pnExponent = pItem->val.expAndMantissa.nExponent; |
| 4124 | |
| 4125 | uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa); |
| 4126 | if(uErr != QCBOR_SUCCESS) { |
| 4127 | pMe->uLastError = (uint8_t)uErr; |
| 4128 | } |
| 4129 | break; |
| 4130 | |
| 4131 | default: |
| 4132 | pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE; |
| 4133 | } |
| 4134 | } |
| 4135 | |
| 4136 | void QCBORDecode_GetDecimalFractionN(QCBORDecodeContext *pMe, |
| 4137 | uint8_t uTagRequirement, |
| 4138 | int64_t nLabel, |
| 4139 | int64_t *pnMantissa, |
| 4140 | int64_t *pnExponent) |
| 4141 | { |
| 4142 | QCBORItem Item; |
| 4143 | |
| 4144 | QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item); |
| 4145 | FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent); |
| 4146 | } |
| 4147 | |
| 4148 | |
| 4149 | |
| 4150 | void QCBORDecode_GetDecimalFractionSZ(QCBORDecodeContext *pMe, |
| 4151 | uint8_t uTagRequirement, |
| 4152 | const char *szLabel, |
| 4153 | int64_t *pnMantissa, |
| 4154 | int64_t *pnExponent) |
| 4155 | { |
| 4156 | QCBORItem Item; |
| 4157 | |
| 4158 | QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item); |
| 4159 | |
| 4160 | FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent); |
| 4161 | } |
| 4162 | |
| 4163 | |
| 4164 | UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer) |
| 4165 | { |
| 4166 | while(uInt & 0xff0000000000UL) { |
| 4167 | uInt = uInt << 8; |
| 4168 | }; |
| 4169 | |
| 4170 | UsefulOutBuf UOB; |
| 4171 | |
| 4172 | UsefulOutBuf_Init(&UOB, Buffer); |
| 4173 | |
| 4174 | while(uInt) { |
| 4175 | UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56)); |
| 4176 | uInt = uInt << 8; |
| 4177 | } |
| 4178 | |
| 4179 | return UsefulOutBuf_OutUBuf(&UOB); |
| 4180 | } |
| 4181 | |
| 4182 | |
| 4183 | void QCBORDecode_GetDecimalFractionBigN(QCBORDecodeContext *pMe, |
| 4184 | uint8_t uTagRequirement, |
| 4185 | int64_t nLabel, |
| 4186 | UsefulBuf pBufferForMantissa, |
| 4187 | UsefulBufC *pMantissa, |
| 4188 | bool *pbIsNegative, |
| 4189 | int64_t *pnExponent) |
| 4190 | { |
| 4191 | QCBORItem Item; |
| 4192 | QCBORError uErr; |
| 4193 | |
| 4194 | QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item); |
| 4195 | |
| 4196 | if(Item.uDataType == QCBOR_TYPE_ARRAY) { |
| 4197 | uErr = QCBORDecode_MantissaAndExponent(pMe, &Item); |
| 4198 | if(uErr != QCBOR_SUCCESS) { |
| 4199 | pMe->uLastError = (uint8_t)uErr; |
| 4200 | return; |
| 4201 | } |
| 4202 | } |
| 4203 | |
| 4204 | uint64_t uMantissa; |
| 4205 | |
| 4206 | switch (Item.uDataType) { |
| 4207 | |
| 4208 | case QCBOR_TYPE_DECIMAL_FRACTION: |
| 4209 | if(Item.val.expAndMantissa.Mantissa.nInt >= 0) { |
| 4210 | uMantissa = (uint64_t)Item.val.expAndMantissa.Mantissa.nInt; |
| 4211 | *pbIsNegative = false; |
| 4212 | } else { |
| 4213 | uMantissa = (uint64_t)-Item.val.expAndMantissa.Mantissa.nInt; |
| 4214 | *pbIsNegative = true; |
| 4215 | } |
| 4216 | *pMantissa = ConvertIntToBigNum(uMantissa, pBufferForMantissa); |
| 4217 | *pnExponent = Item.val.expAndMantissa.nExponent; |
| 4218 | break; |
| 4219 | |
| 4220 | case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM: |
| 4221 | *pnExponent = Item.val.expAndMantissa.nExponent; |
| 4222 | *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum; |
| 4223 | *pbIsNegative = false; |
| 4224 | break; |
| 4225 | |
| 4226 | case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM: |
| 4227 | *pnExponent = Item.val.expAndMantissa.nExponent; |
| 4228 | *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum; |
| 4229 | *pbIsNegative = true; |
| 4230 | break; |
| 4231 | |
| 4232 | default: |
| 4233 | pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE; |
| 4234 | } |
| 4235 | } |