Extracted the class Latch

also fixed a buffer overrun and reduced the code size
This commit is contained in:
Benoit Blanchon
2020-02-13 14:53:54 +01:00
parent d2a67f362f
commit 6e52f242b2
3 changed files with 73 additions and 26 deletions

View File

@ -445,6 +445,15 @@ TEST_CASE("Filtering") {
"[]", "[]",
JSON_ARRAY_SIZE(0) JSON_ARRAY_SIZE(0)
}, },
{
// supports back-slash at the end of skipped string
"\"hell\\",
"false",
1,
DeserializationError::IncompleteInput,
"null",
0
},
}; // clang-format on }; // clang-format on
for (size_t i = 0; i < sizeof(testCases) / sizeof(testCases[0]); i++) { for (size_t i = 0; i < sizeof(testCases) / sizeof(testCases[0]); i++) {

View File

@ -6,6 +6,7 @@
#include <ArduinoJson/Deserialization/deserialize.hpp> #include <ArduinoJson/Deserialization/deserialize.hpp>
#include <ArduinoJson/Json/EscapeSequence.hpp> #include <ArduinoJson/Json/EscapeSequence.hpp>
#include <ArduinoJson/Json/Latch.hpp>
#include <ArduinoJson/Json/Utf16.hpp> #include <ArduinoJson/Json/Utf16.hpp>
#include <ArduinoJson/Json/Utf8.hpp> #include <ArduinoJson/Json/Utf8.hpp>
#include <ArduinoJson/Memory/MemoryPool.hpp> #include <ArduinoJson/Memory/MemoryPool.hpp>
@ -24,20 +25,15 @@ class JsonDeserializer {
JsonDeserializer(MemoryPool &pool, TReader reader, JsonDeserializer(MemoryPool &pool, TReader reader,
TStringStorage stringStorage, uint8_t nestingLimit) TStringStorage stringStorage, uint8_t nestingLimit)
: _pool(&pool), : _pool(&pool),
_reader(reader),
_stringStorage(stringStorage), _stringStorage(stringStorage),
_nestingLimit(nestingLimit), _nestingLimit(nestingLimit),
_loaded(false) { _latch(reader) {}
#ifdef ARDUINOJSON_DEBUG
_ended = false;
#endif
}
template <typename TFilter> template <typename TFilter>
DeserializationError parse(VariantData &variant, TFilter filter) { DeserializationError parse(VariantData &variant, TFilter filter) {
DeserializationError err = parseVariant(variant, filter); DeserializationError err = parseVariant(variant, filter);
if (!err && _current != 0 && !variant.isEnclosed()) { if (!err && _latch.last() != 0 && !variant.isEnclosed()) {
// We don't detect trailing characters earlier, so we need to check now // We don't detect trailing characters earlier, so we need to check now
err = DeserializationError::InvalidInput; err = DeserializationError::InvalidInput;
} }
@ -49,23 +45,14 @@ class JsonDeserializer {
JsonDeserializer &operator=(const JsonDeserializer &); // non-copiable JsonDeserializer &operator=(const JsonDeserializer &); // non-copiable
char current() { char current() {
if (!_loaded) { return _latch.current();
ARDUINOJSON_ASSERT(!_ended);
int c = _reader.read();
#ifdef ARDUINOJSON_DEBUG
if (c <= 0) _ended = true;
#endif
_current = static_cast<char>(c > 0 ? c : 0);
_loaded = true;
}
return _current;
} }
void move() { void move() {
_loaded = false; _latch.clear();
} }
FORCE_INLINE bool eat(char charToSkip) { bool eat(char charToSkip) {
if (current() != charToSkip) return false; if (current() != charToSkip) return false;
move(); move();
return true; return true;
@ -391,7 +378,9 @@ class JsonDeserializer {
move(); move();
if (c == stopChar) break; if (c == stopChar) break;
if (c == '\0') return DeserializationError::IncompleteInput; if (c == '\0') return DeserializationError::IncompleteInput;
if (c == '\\') _reader.read(); if (c == '\\') {
if (current() != '\0') move();
}
} }
return DeserializationError::Ok; return DeserializationError::Ok;
@ -548,14 +537,9 @@ class JsonDeserializer {
} }
MemoryPool *_pool; MemoryPool *_pool;
TReader _reader;
TStringStorage _stringStorage; TStringStorage _stringStorage;
uint8_t _nestingLimit; uint8_t _nestingLimit;
char _current; Latch<TReader> _latch;
bool _loaded;
#ifdef ARDUINOJSON_DEBUG
bool _ended;
#endif
}; };
// deserializeJson(JsonDocument&, const std::string&, ...) // deserializeJson(JsonDocument&, const std::string&, ...)

View File

@ -0,0 +1,54 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#pragma once
#include <ArduinoJson/Polyfills/assert.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TReader>
class Latch {
public:
Latch(TReader reader) : _reader(reader), _loaded(false) {
#ifdef ARDUINOJSON_DEBUG
_ended = false;
#endif
}
void clear() {
_loaded = false;
}
int last() const {
return _current;
}
FORCE_INLINE char current() {
if (!_loaded) {
load();
}
return _current;
}
private:
void load() {
ARDUINOJSON_ASSERT(!_ended);
int c = _reader.read();
#ifdef ARDUINOJSON_DEBUG
if (c <= 0) _ended = true;
#endif
_current = static_cast<char>(c > 0 ? c : 0);
_loaded = true;
}
TReader _reader;
char _current;
bool _loaded;
#ifdef ARDUINOJSON_DEBUG
bool _ended;
#endif
};
} // namespace ARDUINOJSON_NAMESPACE