From b8f2cdfe8d44eb5b68e98828e597fc71d46bbf33 Mon Sep 17 00:00:00 2001 From: Janek Lasocki-Biczysko Date: Thu, 21 May 2015 10:54:01 +0100 Subject: [PATCH] fixes #3 --- src/janeklb/json/JSONCharInputReader.php | 27 ++++++++++++++++++++++-- test/suite.php | 7 ++++++ test/test.php | 18 ++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 test/suite.php diff --git a/src/janeklb/json/JSONCharInputReader.php b/src/janeklb/json/JSONCharInputReader.php index 9593ae6..91bc9a1 100644 --- a/src/janeklb/json/JSONCharInputReader.php +++ b/src/janeklb/json/JSONCharInputReader.php @@ -20,6 +20,7 @@ class JSONCharInputReader private $outputInterface; private $state; private $depth; + private $quoteCount; /** * Create a JSONCharInputReader object @@ -34,6 +35,7 @@ public function __construct(JSONChunkProcessor $outputInterface) $this->state = self::STATE_OUTSIDE; $this->outputInterface = $outputInterface; $this->depth = 0; + $this->quoteCount = 0; } /** @@ -62,8 +64,15 @@ public function readChar($char) case self::STATE_INCURLY: case self::STATE_INSQUARE: + if ($char == '"' && !$this->lastCharIs('\\')) + $this->quoteCount++; + $this->buffer .= $char; + // if quote count is odd we're inside a string.... + if ($this->quoteCount % 2) + break; + $closing = $this->state == self::STATE_INCURLY ? '}' : ']'; $opening = $this->state == self::STATE_INCURLY ? '{' : '['; @@ -71,18 +80,23 @@ public function readChar($char) // if this is another opening brace/bracket character, increase the depth $this->depth++; else if ($char == $closing && --$this->depth == 0) + { // if this is a closing character, decrease the depth and process the buffer if // the bottom was reached $this->processBuffer(); + $this->quoteCount = 0; + } break; // Inside a string case self::STATE_INSTRING: - $this->buffer .= $char; - if ($char == '"') + + if ($char == '"' && !$this->lastCharIs('\\')) $this->state = self::STATE_WAITING; + $this->buffer .= $char; + break; // Waiting on any input within a JSON stream @@ -136,6 +150,15 @@ public function readChar($char) } } + private function lastCharIs($char) { + $len = strlen($this->buffer); + if ($len == 0) + return false; + + $lastChar = $this->buffer[$len - 1]; + return $lastChar === $char; + } + /** * Process the JSON data stream's buffer and reset the state * diff --git a/test/suite.php b/test/suite.php new file mode 100644 index 0000000..d5cb6d5 --- /dev/null +++ b/test/suite.php @@ -0,0 +1,7 @@ +addTestFile(__DIR__ . "/test.php"); +PHPUnit_TextUI_TestRunner::run($suite); diff --git a/test/test.php b/test/test.php index 2cc57e3..424be44 100644 --- a/test/test.php +++ b/test/test.php @@ -105,6 +105,12 @@ public function testMixed() } public function testEscaped() + { + $this->sendInput('"abc\"def",'); + $this->assertObjects('abc"def'); + } + + public function testEscapedInObject() { $this->sendInput('{"x": "x\"a"},{"a\"b":1}'); @@ -118,6 +124,18 @@ public function testEscaped() } public function testBracketsAndBracesInString() + { + $this->sendInput('"str}ing", "str]ing", '); + $this->assertObjects("str}ing", "str]ing"); + } + + public function testBracketsAndBracesInArrayString() + { + $this->sendInput('["str}ing"], ["str]ing"], ["str]ing", "str}ing"]'); + $this->assertObjects(array("str}ing"), array("str]ing"), array("str]ing", "str}ing")); + } + + public function testBracketsAndBracesInObjectString() { $this->sendInput('{"bracket": "val]ue", "brace": "val}ue"}');