Forráskód Böngészése

Fixed deserializer that stopped reading at the first 0xFF (closes #1118)

Benoit Blanchon 6 éve
szülő
commit
ef63757b1a

+ 1 - 0
CHANGELOG.md

@@ -9,6 +9,7 @@ HEAD
 * Fixed `deserializeJson()` when input contains duplicate keys (issue #1095)
 * Improved `deserializeMsgPack()` speed by reading several bytes at once
 * Added detection of Atmel AVR8/GNU C Compiler (issue #1112)
+* Fixed deserializer that stopped reading at the first `0xFF` (PR #1118 by @mikee47)
 
 v6.12.0 (2019-09-05)
 -------

+ 14 - 0
extras/tests/Helpers/Stream.h

@@ -0,0 +1,14 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2019
+// MIT License
+
+#pragma once
+
+// Reproduces Arduino's Stream class
+class Stream  // : public Print
+{
+ public:
+  virtual ~Stream() {}
+  virtual int read() = 0;
+  virtual size_t readBytes(char *buffer, size_t length) = 0;
+};

+ 59 - 0
extras/tests/Misc/Readers.cpp

@@ -2,6 +2,7 @@
 // Copyright Benoit Blanchon 2014-2019
 // MIT License
 
+#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
 #include <ArduinoJson/Deserialization/Reader.hpp>
 #include <catch.hpp>
 
@@ -164,3 +165,61 @@ TEST_CASE("IteratorReader") {
     REQUIRE(buffer[6] == 'g');
   }
 }
+
+class StreamStub : public Stream {
+ public:
+  StreamStub(const char* s) : _stream(s) {}
+
+  int read() {
+    return _stream.get();
+  }
+
+  size_t readBytes(char* buffer, size_t length) {
+    _stream.read(buffer, static_cast<std::streamsize>(length));
+    return static_cast<size_t>(_stream.gcount());
+  }
+
+ private:
+  std::istringstream _stream;
+};
+
+TEST_CASE("Reader<Stream>") {
+  SECTION("read()") {
+    StreamStub src("\x01\xFF");
+    Reader<StreamStub> reader(src);
+
+    REQUIRE(reader.read() == 0x01);
+    REQUIRE(reader.read() == 0xFF);
+    REQUIRE(reader.read() == -1);
+  }
+
+  SECTION("readBytes() all at once") {
+    StreamStub src("ABC");
+    Reader<StreamStub> reader(src);
+
+    char buffer[8] = "abcd";
+    REQUIRE(reader.readBytes(buffer, 4) == 3);
+
+    REQUIRE(buffer[0] == 'A');
+    REQUIRE(buffer[1] == 'B');
+    REQUIRE(buffer[2] == 'C');
+    REQUIRE(buffer[3] == 'd');
+  }
+
+  SECTION("readBytes() in two parts") {
+    StreamStub src("ABCDEF");
+    Reader<StreamStub> reader(src);
+
+    char buffer[12] = "abcdefg";
+    REQUIRE(reader.readBytes(buffer, 4) == 4);
+    REQUIRE(reader.readBytes(buffer + 4, 4) == 2);
+
+    REQUIRE(buffer[0] == 'A');
+    REQUIRE(buffer[1] == 'B');
+    REQUIRE(buffer[2] == 'C');
+    REQUIRE(buffer[3] == 'D');
+    REQUIRE(buffer[4] == 'E');
+    REQUIRE(buffer[5] == 'F');
+    REQUIRE(buffer[6] == 'g');
+  }
+}

+ 6 - 5
src/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp

@@ -11,20 +11,21 @@ namespace ARDUINOJSON_NAMESPACE {
 template <typename TSource>
 struct Reader<TSource,
               typename enable_if<is_base_of<Stream, TSource>::value>::type> {
-  Stream& _stream;
-
  public:
-  explicit Reader(Stream& stream) : _stream(stream) {}
+  explicit Reader(Stream& stream) : _stream(&stream) {}
 
   int read() {
     // don't use _stream.read() as it ignores the timeout
     char c;
-    return _stream.readBytes(&c, 1) ? c : -1;
+    return _stream->readBytes(&c, 1) ? static_cast<unsigned char>(c) : -1;
   }
 
   size_t readBytes(char* buffer, size_t length) {
-    return _stream.readBytes(buffer, length);
+    return _stream->readBytes(buffer, length);
   }
+
+ private:
+  Stream* _stream;
 };
 
 }  // namespace ARDUINOJSON_NAMESPACE