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