forked from bblanchon/ArduinoJson
Fixed ignored Stream
timeout and made sure we don't read more that necessary (issue #422)
This commit is contained in:
@ -5,6 +5,8 @@ HEAD
|
||||
----
|
||||
|
||||
* Fixed parsing of comments (issue #421)
|
||||
* Fixed ignored `Stream` timeout (issue #422)
|
||||
* Made sure we don't read more that necessary (issue #422)
|
||||
|
||||
v5.8.1
|
||||
------
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "StringReader.hpp"
|
||||
#include "StringWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
@ -74,23 +73,23 @@ class JsonParser {
|
||||
|
||||
template <typename TJsonBuffer, typename TString>
|
||||
struct JsonParserBuilder {
|
||||
typedef typename Internals::StringTraits<TString>::Iterator InputIterator;
|
||||
typedef JsonParser<StringReader<InputIterator>, TJsonBuffer &> TParser;
|
||||
typedef typename Internals::StringTraits<TString>::Reader InputReader;
|
||||
typedef JsonParser<InputReader, TJsonBuffer &> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, TString &json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, InputIterator(json), *buffer, nestingLimit);
|
||||
return TParser(buffer, InputReader(json), *buffer, nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer>
|
||||
struct JsonParserBuilder<TJsonBuffer, char *> {
|
||||
typedef typename Internals::StringTraits<char *>::Iterator InputIterator;
|
||||
typedef JsonParser<StringReader<InputIterator>, StringWriter> TParser;
|
||||
typedef typename Internals::StringTraits<char *>::Reader InputReader;
|
||||
typedef JsonParser<InputReader, StringWriter> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, char *json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, InputIterator(json), json, nestingLimit);
|
||||
return TParser(buffer, InputReader(json), json, nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,6 @@ inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::eat(
|
||||
skipSpacesAndComments(reader);
|
||||
if (reader.current() != charToSkip) return false;
|
||||
reader.move();
|
||||
skipSpacesAndComments(reader);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -148,6 +147,7 @@ ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseString() {
|
||||
typename TypeTraits::RemoveReference<TWriter>::type::String str =
|
||||
_writer.startString();
|
||||
|
||||
skipSpacesAndComments(_reader);
|
||||
char c = _reader.current();
|
||||
|
||||
if (isQuote(c)) { // quotes
|
||||
|
@ -1,41 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Parse JSON string to create JsonArrays and JsonObjects
|
||||
// This internal class is not indended to be used directly.
|
||||
// Instead, use JsonBuffer.parseArray() or .parseObject()
|
||||
template <typename TIterator>
|
||||
class StringReader {
|
||||
TIterator _input;
|
||||
char _current, _next;
|
||||
|
||||
public:
|
||||
StringReader(const TIterator& input) : _input(input) {
|
||||
_current = _input.next();
|
||||
_next = _input.next();
|
||||
}
|
||||
|
||||
void move() {
|
||||
_current = _next;
|
||||
_next = _input.next();
|
||||
}
|
||||
|
||||
char current() const {
|
||||
return _current;
|
||||
}
|
||||
|
||||
char next() const {
|
||||
return _next;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -17,15 +17,35 @@ namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
struct ArduinoStreamTraits {
|
||||
class Iterator {
|
||||
class Reader {
|
||||
Stream& _stream;
|
||||
char _current, _next;
|
||||
|
||||
public:
|
||||
Iterator(Stream& stream) : _stream(stream) {}
|
||||
Reader(Stream& stream) : _stream(stream), _current(0), _next(0) {}
|
||||
|
||||
void move() {
|
||||
_current = _next;
|
||||
_next = 0;
|
||||
}
|
||||
|
||||
char current() {
|
||||
if (!_current) _current = read();
|
||||
return _current;
|
||||
}
|
||||
|
||||
char next() {
|
||||
int n = _stream.read();
|
||||
return n >= 0 ? static_cast<char>(n) : '\0';
|
||||
// assumes that current() has been called
|
||||
if (!_next) _next = read();
|
||||
return _next;
|
||||
}
|
||||
|
||||
private:
|
||||
char read() {
|
||||
// don't use _stream.read() as it ignores the timeout
|
||||
char c = 0;
|
||||
_stream.readBytes(&c, 1);
|
||||
return c;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -11,16 +11,22 @@ namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
struct CharPointerTraits {
|
||||
class Iterator {
|
||||
class Reader {
|
||||
const char* _ptr;
|
||||
|
||||
public:
|
||||
Iterator(const char* ptr) : _ptr(ptr ? ptr : "") {}
|
||||
Reader(const char* ptr) : _ptr(ptr ? ptr : "") {}
|
||||
|
||||
char next() {
|
||||
char c = *_ptr;
|
||||
if (c) ++_ptr;
|
||||
return c;
|
||||
void move() {
|
||||
++_ptr;
|
||||
}
|
||||
|
||||
char current() const {
|
||||
return _ptr[0];
|
||||
}
|
||||
|
||||
char next() const {
|
||||
return _ptr[1];
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -11,15 +11,23 @@ namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <>
|
||||
struct StringTraits<const __FlashStringHelper*, void> {
|
||||
class Iterator {
|
||||
class Reader {
|
||||
const char* _ptr;
|
||||
|
||||
public:
|
||||
Iterator(const __FlashStringHelper* ptr)
|
||||
Reader(const __FlashStringHelper* ptr)
|
||||
: _ptr(reinterpret_cast<const char*>(ptr)) {}
|
||||
|
||||
char next() {
|
||||
return pgm_read_byte_near(_ptr++);
|
||||
void move() {
|
||||
_ptr++;
|
||||
}
|
||||
|
||||
char current() const {
|
||||
return pgm_read_byte_near(_ptr);
|
||||
}
|
||||
|
||||
char next() const {
|
||||
return pgm_read_byte_near(_ptr + 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -16,18 +16,35 @@ namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
struct StdStreamTraits {
|
||||
class Iterator {
|
||||
class Reader {
|
||||
std::istream& _stream;
|
||||
char _current, _next;
|
||||
|
||||
public:
|
||||
Iterator(std::istream& stream) : _stream(stream) {}
|
||||
Reader(std::istream& stream) : _stream(stream), _current(0), _next(0) {}
|
||||
|
||||
void move() {
|
||||
_current = _next;
|
||||
_next = 0;
|
||||
}
|
||||
|
||||
char current() {
|
||||
if (!_current) _current = read();
|
||||
return _current;
|
||||
}
|
||||
|
||||
char next() {
|
||||
return _stream.eof() ? '\0' : static_cast<char>(_stream.get());
|
||||
// assumes that current() has been called
|
||||
if (!_next) _next = read();
|
||||
return _next;
|
||||
}
|
||||
|
||||
private:
|
||||
Iterator& operator=(const Iterator&); // Visual Studio C4512
|
||||
Reader& operator=(const Reader&); // Visual Studio C4512
|
||||
|
||||
char read() {
|
||||
return _stream.eof() ? '\0' : static_cast<char>(_stream.get());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -29,8 +29,8 @@ struct StdStringTraits {
|
||||
return static_cast<char*>(dup);
|
||||
}
|
||||
|
||||
struct Iterator : CharPointerTraits::Iterator {
|
||||
Iterator(const TString& str) : CharPointerTraits::Iterator(str.c_str()) {}
|
||||
struct Reader : CharPointerTraits::Reader {
|
||||
Reader(const TString& str) : CharPointerTraits::Reader(str.c_str()) {}
|
||||
};
|
||||
|
||||
static bool equals(const TString& str, const char* expected) {
|
||||
|
@ -60,7 +60,7 @@ TEST(StdStream_Tests, JsonArraySubscript) {
|
||||
}
|
||||
|
||||
TEST(StdStream_Tests, ParseArray) {
|
||||
std::istringstream json("[42]");
|
||||
std::istringstream json(" [ 42 /* comment */ ] ");
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonArray& arr = jsonBuffer.parseArray(json);
|
||||
ASSERT_TRUE(arr.success());
|
||||
@ -69,10 +69,17 @@ TEST(StdStream_Tests, ParseArray) {
|
||||
}
|
||||
|
||||
TEST(StdStream_Tests, ParseObject) {
|
||||
std::istringstream json("{hello:world}");
|
||||
std::istringstream json(" { hello : world // comment\n }");
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonObject& obj = jsonBuffer.parseObject(json);
|
||||
ASSERT_TRUE(obj.success());
|
||||
ASSERT_EQ(1, obj.size());
|
||||
ASSERT_STREQ("world", obj["hello"]);
|
||||
}
|
||||
|
||||
TEST(StdStream_Tests, ShouldNotReadPastTheEnd) {
|
||||
std::istringstream json("{}123");
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
jsonBuffer.parseObject(json);
|
||||
ASSERT_EQ('1', json.get());
|
||||
}
|
||||
|
Reference in New Issue
Block a user