Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
JsonDeserializer.hpp
00001 // ArduinoJson - arduinojson.org 00002 // Copyright Benoit Blanchon 2014-2021 00003 // MIT License 00004 00005 #pragma once 00006 00007 #include <ArduinoJson/Deserialization/deserialize.hpp> 00008 #include <ArduinoJson/Json/EscapeSequence.hpp> 00009 #include <ArduinoJson/Json/Latch.hpp> 00010 #include <ArduinoJson/Json/Utf16.hpp> 00011 #include <ArduinoJson/Json/Utf8.hpp> 00012 #include <ArduinoJson/Memory/MemoryPool.hpp> 00013 #include <ArduinoJson/Numbers/parseNumber.hpp> 00014 #include <ArduinoJson/Polyfills/assert.hpp> 00015 #include <ArduinoJson/Polyfills/type_traits.hpp> 00016 #include <ArduinoJson/Variant/VariantData.hpp> 00017 00018 namespace ARDUINOJSON_NAMESPACE { 00019 00020 template <typename TReader, typename TStringStorage> 00021 class JsonDeserializer { 00022 public: 00023 JsonDeserializer(MemoryPool &pool, TReader reader, 00024 TStringStorage stringStorage) 00025 : _stringStorage(stringStorage), 00026 _foundSomething(false), 00027 _latch(reader), 00028 _pool(&pool), 00029 _error(DeserializationError::Ok) {} 00030 00031 template <typename TFilter> 00032 DeserializationError parse(VariantData &variant, TFilter filter, 00033 NestingLimit nestingLimit) { 00034 parseVariant(variant, filter, nestingLimit); 00035 00036 if (!_error && _latch.last() != 0 && !variant.isEnclosed()) { 00037 // We don't detect trailing characters earlier, so we need to check now 00038 return DeserializationError::InvalidInput; 00039 } 00040 00041 return _error; 00042 } 00043 00044 private: 00045 char current() { 00046 return _latch.current(); 00047 } 00048 00049 void move() { 00050 _latch.clear(); 00051 } 00052 00053 bool eat(char charToSkip) { 00054 if (current() != charToSkip) 00055 return false; 00056 move(); 00057 return true; 00058 } 00059 00060 template <typename TFilter> 00061 bool parseVariant(VariantData &variant, TFilter filter, 00062 NestingLimit nestingLimit) { 00063 if (!skipSpacesAndComments()) 00064 return false; 00065 00066 switch (current()) { 00067 case '[': 00068 if (filter.allowArray()) 00069 return parseArray(variant.toArray(), filter, nestingLimit); 00070 else 00071 return skipArray(nestingLimit); 00072 00073 case '{': 00074 if (filter.allowObject()) 00075 return parseObject(variant.toObject(), filter, nestingLimit); 00076 else 00077 return skipObject(nestingLimit); 00078 00079 case '\"': 00080 case '\'': 00081 if (filter.allowValue()) 00082 return parseStringValue(variant); 00083 else 00084 return skipString(); 00085 00086 default: 00087 if (filter.allowValue()) 00088 return parseNumericValue(variant); 00089 else 00090 return skipNumericValue(); 00091 } 00092 } 00093 00094 bool skipVariant(NestingLimit nestingLimit) { 00095 if (!skipSpacesAndComments()) 00096 return false; 00097 00098 switch (current()) { 00099 case '[': 00100 return skipArray(nestingLimit); 00101 00102 case '{': 00103 return skipObject(nestingLimit); 00104 00105 case '\"': 00106 case '\'': 00107 return skipString(); 00108 00109 default: 00110 return skipNumericValue(); 00111 } 00112 } 00113 00114 template <typename TFilter> 00115 bool parseArray(CollectionData &array, TFilter filter, 00116 NestingLimit nestingLimit) { 00117 if (nestingLimit.reached()) { 00118 _error = DeserializationError::TooDeep; 00119 return false; 00120 } 00121 00122 // Skip opening braket 00123 ARDUINOJSON_ASSERT(current() == '['); 00124 move(); 00125 00126 // Skip spaces 00127 if (!skipSpacesAndComments()) 00128 return false; 00129 00130 // Empty array? 00131 if (eat(']')) 00132 return true; 00133 00134 TFilter memberFilter = filter[0UL]; 00135 00136 // Read each value 00137 for (;;) { 00138 if (memberFilter.allow()) { 00139 // Allocate slot in array 00140 VariantData *value = array.addElement(_pool); 00141 if (!value) { 00142 _error = DeserializationError::NoMemory; 00143 return false; 00144 } 00145 00146 // 1 - Parse value 00147 if (!parseVariant(*value, memberFilter, nestingLimit.decrement())) 00148 return false; 00149 } else { 00150 if (!skipVariant(nestingLimit.decrement())) 00151 return false; 00152 } 00153 00154 // 2 - Skip spaces 00155 if (!skipSpacesAndComments()) 00156 return false; 00157 00158 // 3 - More values? 00159 if (eat(']')) 00160 return true; 00161 if (!eat(',')) { 00162 _error = DeserializationError::InvalidInput; 00163 return false; 00164 } 00165 } 00166 } 00167 00168 bool skipArray(NestingLimit nestingLimit) { 00169 if (nestingLimit.reached()) { 00170 _error = DeserializationError::TooDeep; 00171 return false; 00172 } 00173 00174 // Skip opening braket 00175 ARDUINOJSON_ASSERT(current() == '['); 00176 move(); 00177 00178 // Read each value 00179 for (;;) { 00180 // 1 - Skip value 00181 if (!skipVariant(nestingLimit.decrement())) 00182 return false; 00183 00184 // 2 - Skip spaces 00185 if (!skipSpacesAndComments()) 00186 return false; 00187 00188 // 3 - More values? 00189 if (eat(']')) 00190 return true; 00191 if (!eat(',')) { 00192 _error = DeserializationError::InvalidInput; 00193 return false; 00194 } 00195 } 00196 } 00197 00198 template <typename TFilter> 00199 bool parseObject(CollectionData &object, TFilter filter, 00200 NestingLimit nestingLimit) { 00201 if (nestingLimit.reached()) { 00202 _error = DeserializationError::TooDeep; 00203 return false; 00204 } 00205 00206 // Skip opening brace 00207 ARDUINOJSON_ASSERT(current() == '{'); 00208 move(); 00209 00210 // Skip spaces 00211 if (!skipSpacesAndComments()) 00212 return false; 00213 00214 // Empty object? 00215 if (eat('}')) 00216 return true; 00217 00218 // Read each key value pair 00219 for (;;) { 00220 // Parse key 00221 if (!parseKey()) 00222 return false; 00223 00224 // Skip spaces 00225 if (!skipSpacesAndComments()) 00226 return false; 00227 00228 // Colon 00229 if (!eat(':')) { 00230 _error = DeserializationError::InvalidInput; 00231 return false; 00232 } 00233 00234 const char *key = _stringStorage.c_str(); 00235 00236 TFilter memberFilter = filter[key]; 00237 00238 if (memberFilter.allow()) { 00239 VariantData *variant = object.getMember(adaptString(key)); 00240 if (!variant) { 00241 // Save key in memory pool. 00242 // This MUST be done before adding the slot. 00243 key = _stringStorage.save(); 00244 00245 // Allocate slot in object 00246 VariantSlot *slot = object.addSlot(_pool); 00247 if (!slot) { 00248 _error = DeserializationError::NoMemory; 00249 return false; 00250 } 00251 00252 slot->setKey(key, typename TStringStorage::storage_policy()); 00253 00254 variant = slot->data(); 00255 } 00256 00257 // Parse value 00258 if (!parseVariant(*variant, memberFilter, nestingLimit.decrement())) 00259 return false; 00260 } else { 00261 if (!skipVariant(nestingLimit.decrement())) 00262 return false; 00263 } 00264 00265 // Skip spaces 00266 if (!skipSpacesAndComments()) 00267 return false; 00268 00269 // More keys/values? 00270 if (eat('}')) 00271 return true; 00272 if (!eat(',')) { 00273 _error = DeserializationError::InvalidInput; 00274 return false; 00275 } 00276 00277 // Skip spaces 00278 if (!skipSpacesAndComments()) 00279 return false; 00280 } 00281 } 00282 00283 bool skipObject(NestingLimit nestingLimit) { 00284 if (nestingLimit.reached()) { 00285 _error = DeserializationError::TooDeep; 00286 return false; 00287 } 00288 00289 // Skip opening brace 00290 ARDUINOJSON_ASSERT(current() == '{'); 00291 move(); 00292 00293 // Skip spaces 00294 if (!skipSpacesAndComments()) 00295 return false; 00296 00297 // Empty object? 00298 if (eat('}')) 00299 return true; 00300 00301 // Read each key value pair 00302 for (;;) { 00303 // Skip key 00304 if (!skipVariant(nestingLimit.decrement())) 00305 return false; 00306 00307 // Skip spaces 00308 if (!skipSpacesAndComments()) 00309 return false; 00310 00311 // Colon 00312 if (!eat(':')) { 00313 _error = DeserializationError::InvalidInput; 00314 return false; 00315 } 00316 00317 // Skip value 00318 if (!skipVariant(nestingLimit.decrement())) 00319 return false; 00320 00321 // Skip spaces 00322 if (!skipSpacesAndComments()) 00323 return false; 00324 00325 // More keys/values? 00326 if (eat('}')) 00327 return true; 00328 if (!eat(',')) { 00329 _error = DeserializationError::InvalidInput; 00330 return false; 00331 } 00332 } 00333 } 00334 00335 bool parseKey() { 00336 _stringStorage.startString(); 00337 if (isQuote(current())) { 00338 return parseQuotedString(); 00339 } else { 00340 return parseNonQuotedString(); 00341 } 00342 } 00343 00344 bool parseStringValue(VariantData &variant) { 00345 _stringStorage.startString(); 00346 if (!parseQuotedString()) 00347 return false; 00348 const char *value = _stringStorage.save(); 00349 variant.setStringPointer(value, typename TStringStorage::storage_policy()); 00350 return true; 00351 } 00352 00353 bool parseQuotedString() { 00354 #if ARDUINOJSON_DECODE_UNICODE 00355 Utf16::Codepoint codepoint; 00356 #endif 00357 const char stopChar = current(); 00358 00359 move(); 00360 for (;;) { 00361 char c = current(); 00362 move(); 00363 if (c == stopChar) 00364 break; 00365 00366 if (c == '\0') { 00367 _error = DeserializationError::IncompleteInput; 00368 return false; 00369 } 00370 00371 if (c == '\\') { 00372 c = current(); 00373 00374 if (c == '\0') { 00375 _error = DeserializationError::IncompleteInput; 00376 return false; 00377 } 00378 00379 if (c == 'u') { 00380 #if ARDUINOJSON_DECODE_UNICODE 00381 move(); 00382 uint16_t codeunit; 00383 if (!parseHex4(codeunit)) 00384 return false; 00385 if (codepoint.append(codeunit)) 00386 Utf8::encodeCodepoint(codepoint.value(), _stringStorage); 00387 continue; 00388 #else 00389 _error = DeserializationError::NotSupported; 00390 return false; 00391 #endif 00392 } 00393 00394 // replace char 00395 c = EscapeSequence::unescapeChar(c); 00396 if (c == '\0') { 00397 _error = DeserializationError::InvalidInput; 00398 return false; 00399 } 00400 move(); 00401 } 00402 00403 _stringStorage.append(c); 00404 } 00405 00406 _stringStorage.append('\0'); 00407 00408 if (!_stringStorage.isValid()) { 00409 _error = DeserializationError::NoMemory; 00410 return false; 00411 } 00412 00413 return true; 00414 } 00415 00416 bool parseNonQuotedString() { 00417 char c = current(); 00418 ARDUINOJSON_ASSERT(c); 00419 00420 if (canBeInNonQuotedString(c)) { // no quotes 00421 do { 00422 move(); 00423 _stringStorage.append(c); 00424 c = current(); 00425 } while (canBeInNonQuotedString(c)); 00426 } else { 00427 _error = DeserializationError::InvalidInput; 00428 return false; 00429 } 00430 00431 _stringStorage.append('\0'); 00432 00433 if (!_stringStorage.isValid()) { 00434 _error = DeserializationError::NoMemory; 00435 return false; 00436 } 00437 00438 return true; 00439 } 00440 00441 bool skipString() { 00442 const char stopChar = current(); 00443 00444 move(); 00445 for (;;) { 00446 char c = current(); 00447 move(); 00448 if (c == stopChar) 00449 break; 00450 if (c == '\0') { 00451 _error = DeserializationError::IncompleteInput; 00452 return false; 00453 } 00454 if (c == '\\') { 00455 if (current() != '\0') 00456 move(); 00457 } 00458 } 00459 00460 return true; 00461 } 00462 00463 bool parseNumericValue(VariantData &result) { 00464 uint8_t n = 0; 00465 00466 char c = current(); 00467 while (canBeInNonQuotedString(c) && n < 63) { 00468 move(); 00469 _buffer[n++] = c; 00470 c = current(); 00471 } 00472 _buffer[n] = 0; 00473 00474 c = _buffer[0]; 00475 if (c == 't') { // true 00476 result.setBoolean(true); 00477 if (n != 4) { 00478 _error = DeserializationError::IncompleteInput; 00479 return false; 00480 } 00481 return true; 00482 } 00483 if (c == 'f') { // false 00484 result.setBoolean(false); 00485 if (n != 5) { 00486 _error = DeserializationError::IncompleteInput; 00487 return false; 00488 } 00489 return true; 00490 } 00491 if (c == 'n') { // null 00492 // the variant is already null 00493 if (n != 4) { 00494 _error = DeserializationError::IncompleteInput; 00495 return false; 00496 } 00497 return true; 00498 } 00499 00500 if (!parseNumber(_buffer, result)) { 00501 _error = DeserializationError::InvalidInput; 00502 return false; 00503 } 00504 00505 return true; 00506 } 00507 00508 bool skipNumericValue() { 00509 char c = current(); 00510 while (canBeInNonQuotedString(c)) { 00511 move(); 00512 c = current(); 00513 } 00514 return true; 00515 } 00516 00517 bool parseHex4(uint16_t &result) { 00518 result = 0; 00519 for (uint8_t i = 0; i < 4; ++i) { 00520 char digit = current(); 00521 if (!digit) { 00522 _error = DeserializationError::IncompleteInput; 00523 return false; 00524 } 00525 uint8_t value = decodeHex(digit); 00526 if (value > 0x0F) { 00527 _error = DeserializationError::InvalidInput; 00528 return false; 00529 } 00530 result = uint16_t((result << 4) | value); 00531 move(); 00532 } 00533 return true; 00534 } 00535 00536 static inline bool isBetween(char c, char min, char max) { 00537 return min <= c && c <= max; 00538 } 00539 00540 static inline bool canBeInNonQuotedString(char c) { 00541 return isBetween(c, '0', '9') || isBetween(c, '_', 'z') || 00542 isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.'; 00543 } 00544 00545 static inline bool isQuote(char c) { 00546 return c == '\'' || c == '\"'; 00547 } 00548 00549 static inline uint8_t decodeHex(char c) { 00550 if (c < 'A') 00551 return uint8_t(c - '0'); 00552 c = char(c & ~0x20); // uppercase 00553 return uint8_t(c - 'A' + 10); 00554 } 00555 00556 bool skipSpacesAndComments() { 00557 for (;;) { 00558 switch (current()) { 00559 // end of string 00560 case '\0': 00561 _error = _foundSomething ? DeserializationError::IncompleteInput 00562 : DeserializationError::EmptyInput; 00563 return false; 00564 00565 // spaces 00566 case ' ': 00567 case '\t': 00568 case '\r': 00569 case '\n': 00570 move(); 00571 continue; 00572 00573 #if ARDUINOJSON_ENABLE_COMMENTS 00574 // comments 00575 case '/': 00576 move(); // skip '/' 00577 switch (current()) { 00578 // block comment 00579 case '*': { 00580 move(); // skip '*' 00581 bool wasStar = false; 00582 for (;;) { 00583 char c = current(); 00584 if (c == '\0') { 00585 _error = DeserializationError::IncompleteInput; 00586 return false; 00587 } 00588 if (c == '/' && wasStar) { 00589 move(); 00590 break; 00591 } 00592 wasStar = c == '*'; 00593 move(); 00594 } 00595 break; 00596 } 00597 00598 // trailing comment 00599 case '/': 00600 // no need to skip "//" 00601 for (;;) { 00602 move(); 00603 char c = current(); 00604 if (c == '\0') { 00605 _error = DeserializationError::IncompleteInput; 00606 return false; 00607 } 00608 if (c == '\n') 00609 break; 00610 } 00611 break; 00612 00613 // not a comment, just a '/' 00614 default: 00615 _error = DeserializationError::InvalidInput; 00616 return false; 00617 } 00618 break; 00619 #endif 00620 00621 default: 00622 _foundSomething = true; 00623 return true; 00624 } 00625 } 00626 } 00627 00628 TStringStorage _stringStorage; 00629 bool _foundSomething; 00630 Latch<TReader> _latch; 00631 MemoryPool *_pool; 00632 char _buffer[64]; // using a member instead of a local variable because it 00633 // ended in the recursive path after compiler inlined the 00634 // code 00635 DeserializationError _error; 00636 }; 00637 00638 // 00639 // deserializeJson(JsonDocument&, const std::string&, ...) 00640 // 00641 // ... = NestingLimit 00642 template <typename TString> 00643 DeserializationError deserializeJson( 00644 JsonDocument &doc, const TString &input, 00645 NestingLimit nestingLimit = NestingLimit()) { 00646 return deserialize<JsonDeserializer>(doc, input, nestingLimit, 00647 AllowAllFilter()); 00648 } 00649 // ... = Filter, NestingLimit 00650 template <typename TString> 00651 DeserializationError deserializeJson( 00652 JsonDocument &doc, const TString &input, Filter filter, 00653 NestingLimit nestingLimit = NestingLimit()) { 00654 return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter); 00655 } 00656 // ... = NestingLimit, Filter 00657 template <typename TString> 00658 DeserializationError deserializeJson(JsonDocument &doc, const TString &input, 00659 NestingLimit nestingLimit, Filter filter) { 00660 return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter); 00661 } 00662 00663 // 00664 // deserializeJson(JsonDocument&, std::istream&, ...) 00665 // 00666 // ... = NestingLimit 00667 template <typename TStream> 00668 DeserializationError deserializeJson( 00669 JsonDocument &doc, TStream &input, 00670 NestingLimit nestingLimit = NestingLimit()) { 00671 return deserialize<JsonDeserializer>(doc, input, nestingLimit, 00672 AllowAllFilter()); 00673 } 00674 // ... = Filter, NestingLimit 00675 template <typename TStream> 00676 DeserializationError deserializeJson( 00677 JsonDocument &doc, TStream &input, Filter filter, 00678 NestingLimit nestingLimit = NestingLimit()) { 00679 return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter); 00680 } 00681 // ... = NestingLimit, Filter 00682 template <typename TStream> 00683 DeserializationError deserializeJson(JsonDocument &doc, TStream &input, 00684 NestingLimit nestingLimit, Filter filter) { 00685 return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter); 00686 } 00687 00688 // 00689 // deserializeJson(JsonDocument&, char*, ...) 00690 // 00691 // ... = NestingLimit 00692 template <typename TChar> 00693 DeserializationError deserializeJson( 00694 JsonDocument &doc, TChar *input, 00695 NestingLimit nestingLimit = NestingLimit()) { 00696 return deserialize<JsonDeserializer>(doc, input, nestingLimit, 00697 AllowAllFilter()); 00698 } 00699 // ... = Filter, NestingLimit 00700 template <typename TChar> 00701 DeserializationError deserializeJson( 00702 JsonDocument &doc, TChar *input, Filter filter, 00703 NestingLimit nestingLimit = NestingLimit()) { 00704 return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter); 00705 } 00706 // ... = NestingLimit, Filter 00707 template <typename TChar> 00708 DeserializationError deserializeJson(JsonDocument &doc, TChar *input, 00709 NestingLimit nestingLimit, Filter filter) { 00710 return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter); 00711 } 00712 00713 // 00714 // deserializeJson(JsonDocument&, char*, size_t, ...) 00715 // 00716 // ... = NestingLimit 00717 template <typename TChar> 00718 DeserializationError deserializeJson( 00719 JsonDocument &doc, TChar *input, size_t inputSize, 00720 NestingLimit nestingLimit = NestingLimit()) { 00721 return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit, 00722 AllowAllFilter()); 00723 } 00724 // ... = Filter, NestingLimit 00725 template <typename TChar> 00726 DeserializationError deserializeJson( 00727 JsonDocument &doc, TChar *input, size_t inputSize, Filter filter, 00728 NestingLimit nestingLimit = NestingLimit()) { 00729 return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit, 00730 filter); 00731 } 00732 // ... = NestingLimit, Filter 00733 template <typename TChar> 00734 DeserializationError deserializeJson(JsonDocument &doc, TChar *input, 00735 size_t inputSize, 00736 NestingLimit nestingLimit, Filter filter) { 00737 return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit, 00738 filter); 00739 } 00740 00741 } // namespace ARDUINOJSON_NAMESPACE
Generated on Wed Jul 13 2022 01:10:36 by
1.7.2