Skip to content

Commit

Permalink
add tests & fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
laktak committed Apr 30, 2016
1 parent 907cd24 commit 49d3156
Show file tree
Hide file tree
Showing 24 changed files with 177 additions and 39 deletions.
47 changes: 28 additions & 19 deletions src/HJSON/HJSONParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,21 @@ public function parse($source, $options=[])

$this->keepWsc = $options && $options['keepWsc'];
$this->text = $source;
$this->at = 0;
$this->ch = ' ';
$this->resetAt();
$result = $this->rootValue();
$this->white();

if ($this->ch) throw new HJSONException("Syntax error, found trailing characters");

return $result;
}

function resetAt()
{
$this->at = 0;
$this->ch = ' ';
}

public function parseWsc($source, $options=[])
{
return $this->parse($source, array_merge($options, ['keepWsc' => true]));
Expand All @@ -53,12 +58,16 @@ private function rootValue()
case '[': return $this->_array();
}

// look if we are dealing with a single JSON value (true/false/null/num/"")
// if it is multiline we assume it's a Hjson object without root braces.
for ($i = 0; $i < mb_strlen($this->text); $i++)
if ($this->text[$i] === "\n") return $this->object(true);

return $this->value();
try {
// assume we have a root object without braces
return $this->object(true);
}
catch (HJSONException $e) {
// test if we are dealing with a single JSON value instead (true/false/null/num/"")
$this->resetAt();
try { return $this->value(); }
catch (HJSONException $e2) { throw $e; } // throw original error
}
}

private function value()
Expand Down Expand Up @@ -111,7 +120,7 @@ private function _array()
// assumeing ch === '['

$array = []; $kw = null; $wat = null;

if ($this->keepWsc) {
$array['__WSC__'] = [];
$kw = &$array['__WSC__'];
Expand Down Expand Up @@ -318,7 +327,8 @@ private function keyname()
return $name;
}
else if ($this->ch <= ' ') {
if ($space < 0) $space = mb_strlen($name);
if (!$this->ch) $this->error("Found EOF while looking for a key name (check your syntax)");
else if ($space < 0) $space = mb_strlen($name);
}
else if ($this->ch === '{' || $this->ch === '}' || $this->ch === '[' || $this->ch === ']' || $this->ch === ',') {
$this->error("Found '{$this->ch}' where a key name was expected (check your syntax or use quotes if the key name includes {}[],: or whitespace)");
Expand All @@ -333,10 +343,11 @@ private function tfnns()
// Hjson strings can be quoteless
// returns string, true, false, or null.
$value = $this->ch;
while ($this->next() !== null) {
while (true) {
$isEol = $this->next() === null;
if (mb_strlen($value) === 3 && $value === "'''") return $this->mlString();
$isEol = $this->ch === "\r" || $this->ch === "\n";
$isEol = $isEol || $this->ch === "\r" || $this->ch === "\n";

if ($isEol || $this->ch === ',' ||
$this->ch === '}' || $this->ch === ']' ||
$this->ch === '#' ||
Expand All @@ -360,24 +371,22 @@ private function tfnns()
}
$value .= $this->ch;
}

$this->error("End of input while parsing a value");
}

private function getComment($wat)
{
$i; $wat--;
// remove trailing whitespace
for ($i = $this->at - 2; $i > $wat && $this->text[$i] <= ' ' && $this->text[$i] !== "\n"; $i--);

// but only up to EOL
if ($this->text[$i] === "\n") $i--;
if ($this->text[$i] === "\r") $i--;

$res = mb_substr($this->text, $wat, $i-$wat+1);
for ($i = 0; $i < mb_strlen($res); $i++)
if ($res[$i] > ' ') return $res;

return "";
}
}
17 changes: 9 additions & 8 deletions src/HJSON/HJSONStringifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace HJSON;

function mb_str_split( $string ) {
return preg_split('/(?<!^)(?!$)/u', $string );
function mb_str_split( $string ) {
return preg_split('/(?<!^)(?!$)/u', $string );
}

class HJSONStringifier {
Expand All @@ -12,10 +12,10 @@ class HJSONStringifier {
private $needsQuotes = '/[\x00-\x1f\x7f-\x9f\x{00ad}\x{0600}-\x{0604}\x{070f}\x{17b4}\x{17b5}\x{200c}-\x{200f}\x{2028}-\x{202f}\x{2060}-\x{206f}\x{feff}\x{fff0}-\x{ffff}\x]/u'; // like needsEscape but without \\ and \"
private $needsEscapeML = '/\'\'\'|[\x00-\x09\x0b\x0c\x0e-\x1f\x7f-\x9f\x{00ad}\x{0600}-\x{0604}\x{070f}\x{17b4}\x{17b5}\x{200c}-\x{200f}\x{2028}-\x{202f}\x{2060}-\x{206f}\x{feff}\x{fff0}-\x{ffff}\x]/u'; // ''' || (needsQuotes but without \n and \r)
private $startsWithKeyword = '/^(true|false|null)\s*((,|\]|\}|#|\/\/|\/\*).*)?$/';
private $needsEscapeName = '/[,\{\[\}\]\s]/';
private $needsEscapeName = '/[,\{\[\}\]\s:#"]|\/\/|\/\*|\'\'\'/';
private $gap = '';
private $indent = ' ';

// options
private $eol;
private $keepWsc;
Expand Down Expand Up @@ -111,6 +111,7 @@ private function quote($string=null, $gap=null, $hasComment=null, $isRootObject=
if ($doEscape ||
$this->isWhite($first) ||
$first === '"' ||
$first === "'" && $string[1] === "'" && $string[2] === "'" ||
$first === '#' ||
$first === '/' && ($string[1] === '*' || $string[1] === '/') ||
$first === '{' ||
Expand All @@ -128,11 +129,11 @@ private function quote($string=null, $gap=null, $hasComment=null, $isRootObject=
if (!preg_match($this->needsEscape, $string)) {
return '"' . $string . '"';
}

else if (!preg_match($this->needsEscapeML, $string) && !$isRootObject) {
return $this->mlString($string, $gap);
}

else {
return '"' . $this->quoteReplace($string) . '"';
}
Expand Down Expand Up @@ -214,9 +215,9 @@ private function str($value, $hasComment=null, $noIndent=null, $isRootObject=nul

case 'object':
case 'array':

$isArray = is_array($value);

$kw = null; $kwl = null; // whitespace & comments
if ($this->keepWsc) {
if ($isArray) $kw = @$value['__WSC__'];
Expand Down
4 changes: 4 additions & 0 deletions tests/HJSONParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ public function testAll()
if (count($name) < 2) continue;
$isJson = $name[1] === "json";
$name = $name[0];

// skip empty test
if ($name === "empty") continue;

$this->runEach($name, $file, $isJson, false, false);
$this->runEach($name, $file, $isJson, false, true);
$this->runEach($name, $file, $isJson, true, false);
Expand Down
12 changes: 12 additions & 0 deletions tests/assets/comments_test.hjson
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
// test
# all
// comment
/*
styles
*/
# with lf



# !

{
# hjson style comment
foo1: This is a string value. # part of the string
Expand Down
3 changes: 3 additions & 0 deletions tests/assets/empty_result.hjson
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"": empty
}
3 changes: 3 additions & 0 deletions tests/assets/empty_result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"": "empty"
}
3 changes: 3 additions & 0 deletions tests/assets/empty_test.hjson
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"": empty
}
25 changes: 25 additions & 0 deletions tests/assets/keys_result.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,29 @@
.key: test
trailing: test
trailing2: test
"#c1": test
"foo#bar": test
"//bar": test
"foo//bar": test
"/*foo*/": test
"foo/*foo*/bar": test
"/*": test
"foo/*bar": test
"\"": test
"foo\"bar": test
"'''": test
"foo'''bar": test
":": test
"foo:bar": test
"{": test
"foo{bar": test
"}": test
"foo}bar": test
"[": test
"foo[bar": test
"]": test
"foo]bar": test
nl1: test
nl2: test
nl3: test
}
27 changes: 26 additions & 1 deletion tests/assets/keys_result.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,30 @@
"-test": "test",
".key": "test",
"trailing": "test",
"trailing2": "test"
"trailing2": "test",
"#c1": "test",
"foo#bar": "test",
"//bar": "test",
"foo//bar": "test",
"/*foo*/": "test",
"foo/*foo*/bar": "test",
"/*": "test",
"foo/*bar": "test",
"\"": "test",
"foo\"bar": "test",
"'''": "test",
"foo'''bar": "test",
":": "test",
"foo:bar": "test",
"{": "test",
"foo{bar": "test",
"}": "test",
"foo}bar": "test",
"[": "test",
"foo[bar": "test",
"]": "test",
"foo]bar": "test",
"nl1": "test",
"nl2": "test",
"nl3": "test"
}
37 changes: 37 additions & 0 deletions tests/assets/keys_test.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,41 @@
# trailing spaces in key names are ignored
trailing : test
trailing2 : test
# comment char in key name
"#c1": test
"foo#bar": test
"//bar": test
"foo//bar": test
"/*foo*/": test
"foo/*foo*/bar": test
"/*": test
"foo/*bar": test
# quotes in key name
"\"": test
"foo\"bar": test
"'''": test
"foo'''bar": test
# control char in key name
":": test
"foo:bar": test
"{": test
"foo{bar": test
"}": test
"foo}bar": test
"[": test
"foo[bar": test
"]": test
"foo]bar": test
# newline
nl1:
test
nl2
:
test

nl3

:

test
}
2 changes: 1 addition & 1 deletion tests/assets/oa_result.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
"d": {}
},
[]
]
]
1 change: 1 addition & 0 deletions tests/assets/pass1_result.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
real: -9876.54321
e: 1.23456789e-13
E: 1.23456789e+34
-: 2.3456789012e+76
zero: 0
one: 1
space: " "
Expand Down
3 changes: 2 additions & 1 deletion tests/assets/pass1_result.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"real": -9876.54321,
"e": 1.23456789e-13,
"E": 1.23456789e+34,
"-": 2.3456789012e+76,
"zero": 0,
"one": 1,
"space": " ",
Expand Down Expand Up @@ -71,4 +72,4 @@
2,
2,
"rosebud"
]
]
3 changes: 2 additions & 1 deletion tests/assets/pass1_test.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"real": -9876.543210,
"e": 0.123456789e-12,
"E": 1.234567890E+34,
"-": 23456789012E66,
"zero": 0,
"one": 1,
"space": " ",
Expand Down Expand Up @@ -54,4 +55,4 @@
0.1e1,
1e-1,
1e00,2e+00,2e-00
,"rosebud"]
,"rosebud"]
1 change: 1 addition & 0 deletions tests/assets/pass4_result.hjson
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
10
1 change: 1 addition & 0 deletions tests/assets/pass4_result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
10
2 changes: 2 additions & 0 deletions tests/assets/pass4_test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

10
1 change: 1 addition & 0 deletions tests/assets/passSingle_result.hjson
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo=bar
1 change: 1 addition & 0 deletions tests/assets/passSingle_result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"foo=bar"
1 change: 1 addition & 0 deletions tests/assets/passSingle_test.hjson
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo=bar
6 changes: 4 additions & 2 deletions tests/assets/strings_result.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
foo1c: asdf\"'a\s\w
foo2a: '''"asdf"'''
foo2b: '''"asdf"'''
foo3: asdf'''
foo4: "asdf'''\nasdf"
foo3a: asdf'''
foo3b: "'''asdf"
foo4a: "asdf'''\nasdf"
foo4b: "asdf\n'''asdf"
arr:
[
one
Expand Down
Loading

0 comments on commit 49d3156

Please sign in to comment.