summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenichi Ishigaki <ishigaki@cpan.org>2022-06-27 14:33:15 +0000
committerJames E Keenan <jkeenan@cpan.org>2022-06-27 14:33:15 +0000
commit602e63aa36686ad5cfa326a1b2f20721af9b1ce0 (patch)
tree905095e58c83adf59922f2c6dc779e772debfa62
parent36540e72e5ebd2d98e8833f34b1b25b20553e7cd (diff)
downloadperl-602e63aa36686ad5cfa326a1b2f20721af9b1ce0.tar.gz
JSON-PP: Sync with CPAN version 4.10
From Changes: 4.10 2022-06-24 - fix a regression of decode_error introduced at 4.08 (GH#75, reported by andk++) - convert all tests to use Test::More (GH#70, haarg++) 4.09 2022-05-22 - reverted core boolean support for now (GH#72) - incr_parse() Hangs on Certain Inputs (GH#67, DabeDotCom++) - silence warnings about non-characters on older perls (GH#68, haarg++) 4.08 2022-04-10 - remove unneeded utf8::upgrade and downgrade (GH#59, FGasper++) - core boolean support (GH#62, 63, haarg++) - EBCDIC support (GH#64, khwilliamson++) - shorten a test name (GH#65, khwilliamson)
-rw-r--r--MANIFEST3
-rw-r--r--META.json2
-rwxr-xr-xPorting/Maintainers.pl2
-rw-r--r--cpan/JSON-PP/lib/JSON/PP.pm148
-rw-r--r--cpan/JSON-PP/lib/JSON/PP/Boolean.pm2
-rw-r--r--cpan/JSON-PP/t/001_utf8.t28
-rw-r--r--cpan/JSON-PP/t/004_dwiw_encode.t4
-rw-r--r--cpan/JSON-PP/t/005_dwiw_decode.t4
-rw-r--r--cpan/JSON-PP/t/008_pc_base.t2
-rw-r--r--cpan/JSON-PP/t/014_latin1.t8
-rw-r--r--cpan/JSON-PP/t/105_esc_slash.t2
-rw-r--r--cpan/JSON-PP/t/106_allow_barekey.t2
-rw-r--r--cpan/JSON-PP/t/107_allow_singlequote.t2
-rw-r--r--cpan/JSON-PP/t/108_decode.t17
-rw-r--r--cpan/JSON-PP/t/109_encode.t36
-rw-r--r--cpan/JSON-PP/t/112_upgrade.t8
-rw-r--r--cpan/JSON-PP/t/119_incr_parse_utf8.t75
-rw-r--r--cpan/JSON-PP/t/120_incr_parse_truncated.t218
-rw-r--r--cpan/JSON-PP/t/rt_122270_old_xs_boolean.t33
19 files changed, 495 insertions, 101 deletions
diff --git a/MANIFEST b/MANIFEST
index d4899f40f2..39077a532e 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1302,9 +1302,12 @@ cpan/JSON-PP/t/115_tie_ixhash.t
cpan/JSON-PP/t/116_incr_parse_fixed.t
cpan/JSON-PP/t/117_numbers.t
cpan/JSON-PP/t/118_boolean_values.t
+cpan/JSON-PP/t/119_incr_parse_utf8.t
+cpan/JSON-PP/t/120_incr_parse_truncated.t
cpan/JSON-PP/t/gh_28_json_test_suite.t
cpan/JSON-PP/t/gh_29_trailing_false_value.t
cpan/JSON-PP/t/rt_116998_wrong_character_offset.t
+cpan/JSON-PP/t/rt_122270_old_xs_boolean.t
cpan/JSON-PP/t/rt_90071_incr_parse.t
cpan/JSON-PP/t/zero-mojibake.t
cpan/libnet/lib/Net/Cmd.pm
diff --git a/META.json b/META.json
index 7ddea5a37b..d0691e709e 100644
--- a/META.json
+++ b/META.json
@@ -119,5 +119,5 @@
}
},
"version" : "5.037002",
- "x_serialization_backend" : "JSON::PP version 4.07"
+ "x_serialization_backend" : "JSON::PP version 4.10"
}
diff --git a/Porting/Maintainers.pl b/Porting/Maintainers.pl
index 5460ef6884..ca869eadb8 100755
--- a/Porting/Maintainers.pl
+++ b/Porting/Maintainers.pl
@@ -680,7 +680,7 @@ use File::Glob qw(:case);
},
'JSON::PP' => {
- 'DISTRIBUTION' => 'ISHIGAKI/JSON-PP-4.07.tar.gz',
+ 'DISTRIBUTION' => 'ISHIGAKI/JSON-PP-4.10.tar.gz',
'FILES' => q[cpan/JSON-PP],
},
diff --git a/cpan/JSON-PP/lib/JSON/PP.pm b/cpan/JSON-PP/lib/JSON/PP.pm
index ff23fc7c0f..e34b927898 100644
--- a/cpan/JSON-PP/lib/JSON/PP.pm
+++ b/cpan/JSON-PP/lib/JSON/PP.pm
@@ -14,7 +14,7 @@ use JSON::PP::Boolean;
use Carp ();
#use Devel::Peek;
-$JSON::PP::VERSION = '4.07';
+$JSON::PP::VERSION = '4.10';
@JSON::PP::EXPORT = qw(encode_json decode_json from_json to_json);
@@ -47,6 +47,17 @@ use constant P_ALLOW_TAGS => 19;
use constant OLD_PERL => $] < 5.008 ? 1 : 0;
use constant USE_B => $ENV{PERL_JSON_PP_USE_B} || 0;
+my $invalid_char_re;
+
+BEGIN {
+ $invalid_char_re = "[";
+ for my $i (0 .. 0x01F, 0x22, 0x5c) { # '/' is ok
+ $invalid_char_re .= quotemeta chr utf8::unicode_to_native($i);
+ }
+
+ $invalid_char_re = qr/$invalid_char_re]/;
+}
+
BEGIN {
if (USE_B) {
require B;
@@ -326,14 +337,6 @@ sub allow_bigint {
$str .= "\n" if ( $indent ); # JSON::XS 2.26 compatible
- unless ($ascii or $latin1 or $utf8) {
- utf8::upgrade($str);
- }
-
- if ($props->[ P_SHRINK ]) {
- utf8::downgrade($str, 1);
- }
-
return $str;
}
@@ -527,9 +530,11 @@ sub allow_bigint {
sub string_to_json {
my ($self, $arg) = @_;
- $arg =~ s/([\x22\x5c\n\r\t\f\b])/$esc{$1}/g;
+ $arg =~ s/(["\\\n\r\t\f\b])/$esc{$1}/g;
$arg =~ s/\//\\\//g if ($escape_slash);
- $arg =~ s/([\x00-\x08\x0b\x0e-\x1f])/'\\u00' . unpack('H2', $1)/eg;
+
+ # On ASCII platforms, matches [\x00-\x08\x0b\x0e-\x1f]
+ $arg =~ s/([^\n\t\c?[:^cntrl:][:^ascii:]])/'\\u00' . unpack('H2', $1)/eg;
if ($ascii) {
$arg = JSON_PP_encode_ascii($arg);
@@ -604,7 +609,7 @@ sub allow_bigint {
sub _encode_ascii {
join('',
map {
- $_ <= 127 ?
+ chr($_) =~ /[[:ascii:]]/ ?
chr($_) :
$_ <= 65535 ?
sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_));
@@ -658,11 +663,11 @@ BEGIN {
{ # PARSE
my %escapes = ( # by Jeremy Muhlich <jmuhlich [at] bitflood.org>
- b => "\x8",
- t => "\x9",
- n => "\xA",
- f => "\xC",
- r => "\xD",
+ b => "\b",
+ t => "\t",
+ n => "\n",
+ f => "\f",
+ r => "\r",
'\\' => '\\',
'"' => '"',
'/' => '/',
@@ -736,7 +741,6 @@ BEGIN {
}
}
else {
- utf8::upgrade( $text );
utf8::encode( $text );
}
@@ -853,7 +857,8 @@ BEGIN {
decode_error("surrogate pair expected");
}
- if ( ( my $hex = hex( $u ) ) > 127 ) {
+ my $hex = hex( $u );
+ if ( chr $u =~ /[[:^ascii:]]/ ) {
$is_utf8 = 1;
$s .= JSON_PP_decode_unicode($u) || next;
}
@@ -873,7 +878,7 @@ BEGIN {
}
else{
- if ( ord $ch > 127 ) {
+ if ( $ch =~ /[[:^ascii:]]/ ) {
unless( $ch = is_valid_utf8($ch) ) {
$at -= 1;
decode_error("malformed UTF-8 character in JSON string");
@@ -886,10 +891,12 @@ BEGIN {
}
if (!$loose) {
- if ($ch =~ /[\x00-\x1f\x22\x5c]/) { # '/' ok
+ if ($ch =~ $invalid_char_re) { # '/' ok
if (!$relaxed or $ch ne "\t") {
$at--;
- decode_error('invalid character encountered while parsing JSON string');
+ decode_error(sprintf "invalid character 0x%X"
+ . " encountered while parsing JSON string",
+ ord $ch);
}
}
}
@@ -1102,7 +1109,7 @@ BEGIN {
sub bareKey { # doesn't strictly follow Standard ECMA-262 3rd Edition
my $key;
- while($ch =~ /[^\x00-\x23\x25-\x2F\x3A-\x40\x5B-\x5E\x60\x7B-\x7F]/){
+ while($ch =~ /[\$\w[:^ascii:]]/){
$key .= $ch;
next_chr();
}
@@ -1235,31 +1242,55 @@ BEGIN {
return $is_dec ? $v/1.0 : 0+$v;
}
+ # Compute how many bytes are in the longest legal official Unicode
+ # character
+ my $max_unicode_length = do {
+ BEGIN { $] >= 5.006 and require warnings and warnings->unimport('utf8') }
+ chr 0x10FFFF;
+ };
+ utf8::encode($max_unicode_length);
+ $max_unicode_length = length $max_unicode_length;
sub is_valid_utf8 {
- $utf8_len = $_[0] =~ /[\x00-\x7F]/ ? 1
- : $_[0] =~ /[\xC2-\xDF]/ ? 2
- : $_[0] =~ /[\xE0-\xEF]/ ? 3
- : $_[0] =~ /[\xF0-\xF4]/ ? 4
- : 0
- ;
-
- return unless $utf8_len;
-
- my $is_valid_utf8 = substr($text, $at - 1, $utf8_len);
-
- return ( $is_valid_utf8 =~ /^(?:
- [\x00-\x7F]
- |[\xC2-\xDF][\x80-\xBF]
- |[\xE0][\xA0-\xBF][\x80-\xBF]
- |[\xE1-\xEC][\x80-\xBF][\x80-\xBF]
- |[\xED][\x80-\x9F][\x80-\xBF]
- |[\xEE-\xEF][\x80-\xBF][\x80-\xBF]
- |[\xF0][\x90-\xBF][\x80-\xBF][\x80-\xBF]
- |[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF]
- |[\xF4][\x80-\x8F][\x80-\xBF][\x80-\xBF]
- )$/x ) ? $is_valid_utf8 : '';
+ # Returns undef (setting $utf8_len to 0) unless the next bytes in $text
+ # comprise a well-formed UTF-8 encoded character, in which case,
+ # return those bytes, setting $utf8_len to their count.
+
+ my $start_point = substr($text, $at - 1);
+
+ # Look no further than the maximum number of bytes in a single
+ # character
+ my $limit = $max_unicode_length;
+ $limit = length($start_point) if $limit > length($start_point);
+
+ # Find the number of bytes comprising the first character in $text
+ # (without having to know the details of its internal representation).
+ # This loop will iterate just once on well-formed input.
+ while ($limit > 0) { # Until we succeed or exhaust the input
+ my $copy = substr($start_point, 0, $limit);
+
+ # decode() will return true if all bytes are valid; false
+ # if any aren't.
+ if (utf8::decode($copy)) {
+
+ # Is valid: get the first character, convert back to bytes,
+ # and return those bytes.
+ $copy = substr($copy, 0, 1);
+ utf8::encode($copy);
+ $utf8_len = length $copy;
+ return substr($start_point, 0, $utf8_len);
+ }
+
+ # If it didn't work, it could be that there is a full legal character
+ # followed by a partial or malformed one. Narrow the window and
+ # try again.
+ $limit--;
+ }
+
+ # Failed to find a legal UTF-8 character.
+ $utf8_len = 0;
+ return;
}
@@ -1278,14 +1309,14 @@ BEGIN {
}
for my $c ( unpack( $type, $str ) ) { # emulate pv_uni_display() ?
- $mess .= $c == 0x07 ? '\a'
- : $c == 0x09 ? '\t'
- : $c == 0x0a ? '\n'
- : $c == 0x0d ? '\r'
- : $c == 0x0c ? '\f'
- : $c < 0x20 ? sprintf('\x{%x}', $c)
- : $c == 0x5c ? '\\\\'
- : $c < 0x80 ? chr($c)
+ my $chr_c = chr($c);
+ $mess .= $chr_c eq '\\' ? '\\\\'
+ : $chr_c =~ /[[:print:]]/ ? $chr_c
+ : $chr_c eq '\a' ? '\a'
+ : $chr_c eq '\t' ? '\t'
+ : $chr_c eq '\n' ? '\n'
+ : $chr_c eq '\r' ? '\r'
+ : $chr_c eq '\f' ? '\f'
: sprintf('\x{%x}', $c)
;
if ( length $mess >= 20 ) {
@@ -1534,10 +1565,6 @@ sub incr_parse {
$self->{incr_text} = '' unless ( defined $self->{incr_text} );
if ( defined $text ) {
- if ( utf8::is_utf8( $text ) and !utf8::is_utf8( $self->{incr_text} ) ) {
- utf8::upgrade( $self->{incr_text} ) ;
- utf8::decode( $self->{incr_text} ) ;
- }
$self->{incr_text} .= $text;
}
@@ -1564,7 +1591,6 @@ sub incr_parse {
}
unless ( $coder->get_utf8 ) {
- utf8::upgrade( $self->{incr_text} );
utf8::decode( $self->{incr_text} );
}
@@ -1605,7 +1631,7 @@ INCR_PARSE:
while ( $len > $p ) {
$s = substr( $text, $p, 1 );
last INCR_PARSE unless defined $s;
- if ( ord($s) > 0x20 ) {
+ if ( ord($s) > ord " " ) {
if ( $s eq '#' ) {
$self->{incr_mode} = INCR_M_C0;
redo INCR_PARSE;
@@ -1632,6 +1658,7 @@ INCR_PARSE:
}
next;
} elsif ( $mode == INCR_M_TFN ) {
+ last INCR_PARSE if $p >= $len && $self->{incr_nest};
while ( $len > $p ) {
$s = substr( $text, $p++, 1 );
next if defined $s and $s =~ /[rueals]/;
@@ -1643,6 +1670,7 @@ INCR_PARSE:
last INCR_PARSE unless $self->{incr_nest};
redo INCR_PARSE;
} elsif ( $mode == INCR_M_NUM ) {
+ last INCR_PARSE if $p >= $len && $self->{incr_nest};
while ( $len > $p ) {
$s = substr( $text, $p++, 1 );
next if defined $s and $s =~ /[0-9eE.+\-]/;
@@ -1679,7 +1707,7 @@ INCR_PARSE:
if ( $s eq "\x00" ) {
$p--;
last INCR_PARSE;
- } elsif ( $s eq "\x09" or $s eq "\x0a" or $s eq "\x0d" or $s eq "\x20" ) {
+ } elsif ( $s =~ /^[\t\n\r ]$/) {
if ( !$self->{incr_nest} ) {
$p--; # do not eat the whitespace, let the next round do it
last INCR_PARSE;
diff --git a/cpan/JSON-PP/lib/JSON/PP/Boolean.pm b/cpan/JSON-PP/lib/JSON/PP/Boolean.pm
index d1ee0a477c..23e71d6e41 100644
--- a/cpan/JSON-PP/lib/JSON/PP/Boolean.pm
+++ b/cpan/JSON-PP/lib/JSON/PP/Boolean.pm
@@ -10,7 +10,7 @@ overload::import('overload',
fallback => 1,
);
-$JSON::PP::Boolean::VERSION = '4.07';
+$JSON::PP::Boolean::VERSION = '4.10';
1;
diff --git a/cpan/JSON-PP/t/001_utf8.t b/cpan/JSON-PP/t/001_utf8.t
index e160f82416..4044e44690 100644
--- a/cpan/JSON-PP/t/001_utf8.t
+++ b/cpan/JSON-PP/t/001_utf8.t
@@ -10,17 +10,23 @@ BEGIN { $ENV{PERL_JSON_BACKEND} = 0; }
use utf8;
use JSON::PP;
-
-ok (JSON::PP->new->allow_nonref (1)->utf8 (1)->encode ("ü") eq "\"\xc3\xbc\"");
-ok (JSON::PP->new->allow_nonref (1)->encode ("ü") eq "\"ü\"");
-ok (JSON::PP->new->allow_nonref (1)->ascii (1)->utf8 (1)->encode (chr 0x8000) eq '"\u8000"');
-ok (JSON::PP->new->allow_nonref (1)->ascii (1)->utf8 (1)->pretty (1)->encode (chr 0x10402) eq "\"\\ud801\\udc02\"\n");
-
-eval { JSON::PP->new->allow_nonref (1)->utf8 (1)->decode ('"ü"') };
+my $pilcrow_utf8 = (ord "^" == 0x5E) ? "\xc2\xb6" # 8859-1
+ : (ord "^" == 0x5F) ? "\x80\x65" # CP 1024
+ : "\x78\x64"; # assume CP 037
+is (JSON::PP->new->allow_nonref (1)->utf8 (1)->encode ("¶"), "\"$pilcrow_utf8\"");
+is (JSON::PP->new->allow_nonref (1)->encode ("¶"), "\"¶\"");
+is (JSON::PP->new->allow_nonref (1)->ascii (1)->utf8 (1)->encode (chr 0x8000), '"\u8000"');
+is (JSON::PP->new->allow_nonref (1)->ascii (1)->utf8 (1)->pretty (1)->encode (chr 0x10402), "\"\\ud801\\udc02\"\n");
+
+eval { JSON::PP->new->allow_nonref (1)->utf8 (1)->decode ('"¶"') };
ok $@ =~ /malformed UTF-8/;
-ok (JSON::PP->new->allow_nonref (1)->decode ('"ü"') eq "ü");
-ok (JSON::PP->new->allow_nonref (1)->decode ('"\u00fc"') eq "ü");
-ok (JSON::PP->new->allow_nonref (1)->decode ('"\ud801\udc02' . "\x{10204}\"") eq "\x{10402}\x{10204}");
-ok (JSON::PP->new->allow_nonref (1)->decode ('"\"\n\\\\\r\t\f\b"') eq "\"\012\\\015\011\014\010");
+is (JSON::PP->new->allow_nonref (1)->decode ('"¶"'), "¶");
+is (JSON::PP->new->allow_nonref (1)->decode ('"\u00b6"'), "¶");
+is (JSON::PP->new->allow_nonref (1)->decode ('"\ud801\udc02' . "\x{10204}\""), "\x{10402}\x{10204}");
+
+my $controls = (ord "^" == 0x5E) ? "\012\\\015\011\014\010"
+ : (ord "^" == 0x5F) ? "\025\\\015\005\014\026" # CP 1024
+ : "\045\\\015\005\014\026"; # assume CP 037
+is (JSON::PP->new->allow_nonref (1)->decode ('"\"\n\\\\\r\t\f\b"'), "\"$controls");
diff --git a/cpan/JSON-PP/t/004_dwiw_encode.t b/cpan/JSON-PP/t/004_dwiw_encode.t
index 32e4500fee..f413e87650 100644
--- a/cpan/JSON-PP/t/004_dwiw_encode.t
+++ b/cpan/JSON-PP/t/004_dwiw_encode.t
@@ -7,12 +7,10 @@
use strict;
use warnings;
-use Test;
+use Test::More tests => 5;
# main
{
- BEGIN { plan tests => 5 }
-
BEGIN { $ENV{PERL_JSON_BACKEND} = 0; }
use JSON::PP;
diff --git a/cpan/JSON-PP/t/005_dwiw_decode.t b/cpan/JSON-PP/t/005_dwiw_decode.t
index 9bfe2fd07e..ab195ad425 100644
--- a/cpan/JSON-PP/t/005_dwiw_decode.t
+++ b/cpan/JSON-PP/t/005_dwiw_decode.t
@@ -7,12 +7,10 @@
use strict;
use warnings;
-use Test;
+use Test::More tests => 7;
# main
{
- BEGIN { plan tests => 7 }
-
BEGIN { $ENV{PERL_JSON_BACKEND} = 0; }
use JSON::PP;
diff --git a/cpan/JSON-PP/t/008_pc_base.t b/cpan/JSON-PP/t/008_pc_base.t
index 762edfd965..e717baefbe 100644
--- a/cpan/JSON-PP/t/008_pc_base.t
+++ b/cpan/JSON-PP/t/008_pc_base.t
@@ -77,7 +77,7 @@ $obj = $pc->decode($js);
is($obj->[0],"\x01");
$obj = ["\e"];
-is($js = $pc->encode($obj),'["\\u001b"]');
+is($js = $pc->encode($obj), (ord("A") == 65) ? '["\\u001b"]' : '["\\u0027"]');
$obj = $pc->decode($js);
is($obj->[0],"\e");
diff --git a/cpan/JSON-PP/t/014_latin1.t b/cpan/JSON-PP/t/014_latin1.t
index 7030db8637..cef90580f1 100644
--- a/cpan/JSON-PP/t/014_latin1.t
+++ b/cpan/JSON-PP/t/014_latin1.t
@@ -11,9 +11,9 @@ use JSON::PP;
my $pp = JSON::PP->new->latin1->allow_nonref;
-ok ($pp->encode ("\x{12}\x{89} ") eq "\"\\u0012\x{89} \"");
-ok ($pp->encode ("\x{12}\x{89}\x{abc}") eq "\"\\u0012\x{89}\\u0abc\"");
+ok ($pp->encode ("\x{12}\x{b6} ") eq "\"\\u0012\x{b6} \"");
+ok ($pp->encode ("\x{12}\x{b6}\x{abc}") eq "\"\\u0012\x{b6}\\u0abc\"");
-ok ($pp->decode ("\"\\u0012\x{89}\"" ) eq "\x{12}\x{89}");
-ok ($pp->decode ("\"\\u0012\x{89}\\u0abc\"") eq "\x{12}\x{89}\x{abc}");
+ok ($pp->decode ("\"\\u0012\x{b6}\"" ) eq "\x{12}\x{b6}");
+ok ($pp->decode ("\"\\u0012\x{b6}\\u0abc\"") eq "\x{12}\x{b6}\x{abc}");
diff --git a/cpan/JSON-PP/t/105_esc_slash.t b/cpan/JSON-PP/t/105_esc_slash.t
index ae2d7d207b..56f415cf02 100644
--- a/cpan/JSON-PP/t/105_esc_slash.t
+++ b/cpan/JSON-PP/t/105_esc_slash.t
@@ -1,6 +1,6 @@
use Test::More;
-use strict;
+use strict;
use warnings;
BEGIN { plan tests => 2 };
BEGIN { $ENV{PERL_JSON_BACKEND} = 0; }
diff --git a/cpan/JSON-PP/t/106_allow_barekey.t b/cpan/JSON-PP/t/106_allow_barekey.t
index f5c9189346..20918bbdc2 100644
--- a/cpan/JSON-PP/t/106_allow_barekey.t
+++ b/cpan/JSON-PP/t/106_allow_barekey.t
@@ -1,6 +1,6 @@
use Test::More;
-use strict;
+use strict;
use warnings;
BEGIN { plan tests => 2 };
BEGIN { $ENV{PERL_JSON_BACKEND} = 0; }
diff --git a/cpan/JSON-PP/t/107_allow_singlequote.t b/cpan/JSON-PP/t/107_allow_singlequote.t
index 5948f41841..b3462f9775 100644
--- a/cpan/JSON-PP/t/107_allow_singlequote.t
+++ b/cpan/JSON-PP/t/107_allow_singlequote.t
@@ -1,6 +1,6 @@
use Test::More;
-use strict;
+use strict;
use warnings;
BEGIN { plan tests => 4 };
BEGIN { $ENV{PERL_JSON_BACKEND} = 0; }
diff --git a/cpan/JSON-PP/t/108_decode.t b/cpan/JSON-PP/t/108_decode.t
index e0cec29015..3282c853ad 100644
--- a/cpan/JSON-PP/t/108_decode.t
+++ b/cpan/JSON-PP/t/108_decode.t
@@ -5,10 +5,12 @@ use strict;
use warnings;
use Test::More;
-BEGIN { plan tests => 6 };
+BEGIN { plan tests => 7 };
BEGIN { $ENV{PERL_JSON_BACKEND} = 0; }
+my $isASCII = ord "A" == 65;
+
use JSON::PP;
no utf8;
@@ -22,16 +24,23 @@ is($json->decode(q|"\u00c3\u00bc"|), "\xc3\xbc"); # utf8
my $str = 'あ'; # Japanese 'a' in utf8
-is($json->decode(q|"\u00e3\u0081\u0082"|), $str);
+is($json->decode(($isASCII) ? q|"\u00e3\u0081\u0082"|
+ : q|"\u00ce\u0043\u0043"|),
+ $str);
utf8::decode($str); # usually UTF-8 flagged on, but no-op for 5.005.
is($json->decode(q|"\u3042"|), $str);
-my $utf8 = $json->decode(q|"\ud808\udf45"|); # chr 12345
+# chr 0x12400, which was chosen because it has the same representation in
+# both EBCDIC 1047 and 037
+my $utf8 = $json->decode(q|"\ud809\udc00"|);
utf8::encode($utf8); # UTF-8 flagged off
-is($utf8, "\xf0\x92\x8d\x85");
+is($utf8, ($isASCII) ? "\xf0\x92\x90\x80" : "\xDE\x4A\x41\x41");
+eval { $json->decode(q|{"action":"foo" "method":"bar","tid":1}|) };
+my $error = $@;
+like $error => qr!""method":"bar","tid"..."!;
diff --git a/cpan/JSON-PP/t/109_encode.t b/cpan/JSON-PP/t/109_encode.t
index 95f7764ff2..322425ff7d 100644
--- a/cpan/JSON-PP/t/109_encode.t
+++ b/cpan/JSON-PP/t/109_encode.t
@@ -9,20 +9,46 @@ BEGIN { plan tests => 7 };
BEGIN { $ENV{PERL_JSON_BACKEND} = 0; }
+my $isASCII = ord "A" == 65;
+
use JSON::PP;
no utf8;
my $json = JSON::PP->new->allow_nonref;
-is($json->encode("ü"), q|"ü"|); # as is
+# U+00B6 chosen because it works on both ASCII and EBCDIC
+is($json->encode("¶"), q|"¶"|); # as is
$json->ascii;
-is($json->encode("\xfc"), q|"\u00fc"|); # latin1
-is($json->encode("\xc3\xbc"), q|"\u00c3\u00bc"|); # utf8
-is($json->encode("ü"), q|"\u00c3\u00bc"|); # utf8
-is($json->encode('あ'), q|"\u00e3\u0081\u0082"|);
+if ($] < 5.008) {
+ is($json->encode("\xb6"), q|"\u00b6"|); # latin1
+ is($json->encode("\xc2\xb6"), q|"\u00c2\u00b6"|); # utf8
+ is($json->encode("¶"), q|"\u00c2\u00b6"|); # utf8
+ is($json->encode('あ'), q|"\u00e3\u0081\u0082"|);
+}
+else {
+ is($json->encode("\xb6"), q|"\u00b6"|); # latin1
+
+ if (ord "A" == 65) {
+ is($json->encode("\xc2\xb6"), q|"\u00c2\u00b6"|); # utf8
+ is($json->encode("¶"), q|"\u00c2\u00b6"|); # utf8
+ is($json->encode('あ'), q|"\u00e3\u0081\u0082"|);
+ }
+ else {
+ if (ord '^' == 95) { # EBCDIC 1047
+ is($json->encode("\x80\x65"), q|"\u0080\u0065"|); # utf8
+ is($json->encode("¶"), q|"\u0080\u0065"|); # utf8
+ }
+ else { # Assume EBCDIC 037
+ is($json->encode("\x78\x64"), q|"\u0078\u0064"|); # utf8
+ is($json->encode("¶"), q|"\u0078\u0064"|); # utf8
+ }
+
+ is($json->encode('あ'), (q|"\u00ce\u0043\u0043"|));
+ }
+}
if ($] >= 5.006) {
is($json->encode(chr hex 3042 ), q|"\u3042"|);
diff --git a/cpan/JSON-PP/t/112_upgrade.t b/cpan/JSON-PP/t/112_upgrade.t
index 853439a174..681ce67f65 100644
--- a/cpan/JSON-PP/t/112_upgrade.t
+++ b/cpan/JSON-PP/t/112_upgrade.t
@@ -9,17 +9,17 @@ BEGIN { $ENV{PERL_JSON_BACKEND} = 0; }
use JSON::PP;
my $json = JSON::PP->new->allow_nonref->utf8;
-my $str = '\\u00c8';
+my $str = '\\u00b6';
-my $value = $json->decode( '"\\u00c8"' );
+my $value = $json->decode( '"\\u00b6"' );
#use Devel::Peek;
#Dump( $value );
-is( $value, chr 0xc8 );
+is( $value, chr 0xb6 );
ok( utf8::is_utf8( $value ) );
-eval { $json->decode( '"' . chr(0xc8) . '"' ) };
+eval { $json->decode( '"' . chr(0xb6) . '"' ) };
ok( $@ =~ /malformed UTF-8 character in JSON string/ );
diff --git a/cpan/JSON-PP/t/119_incr_parse_utf8.t b/cpan/JSON-PP/t/119_incr_parse_utf8.t
new file mode 100644
index 0000000000..90916fbbe2
--- /dev/null
+++ b/cpan/JSON-PP/t/119_incr_parse_utf8.t
@@ -0,0 +1,75 @@
+use strict;
+use warnings;
+use Test::More tests => 24;
+
+use utf8;
+use JSON::PP;
+use Encode;
+use charnames qw< :full >;
+
+use vars qw< @vs >;
+
+############################################################
+### These first tests mimic the ones in `t/001_utf8.t` ###
+############################################################
+
+scalar eval { JSON::PP->new->allow_nonref (1)->utf8 (1)->incr_parse ('"ü"') };
+like $@, qr/malformed UTF-8/;
+
+ok (JSON::PP->new->allow_nonref (1)->incr_parse ('"ü"') eq "ü");
+ok (JSON::PP->new->allow_nonref (1)->incr_parse ('"\u00fc"') eq "ü");
+ok (JSON::PP->new->allow_nonref (1)->incr_parse ('"\ud801\udc02' . "\x{10204}\"") eq "\x{10402}\x{10204}");
+ok (JSON::PP->new->allow_nonref (1)->incr_parse ('"\"\n\\\\\r\t\f\b"') eq "\"\012\\\015\011\014\010");
+
+
+my $JSON_TXT = <<JSON_TXT;
+{ "a": "1" }
+{ "b": "\N{BULLET}" }
+{ "c": "3" }
+JSON_TXT
+
+#######################
+### With '->utf8' ###
+#######################
+
+@vs = eval { JSON::PP->new->utf8->incr_parse( $JSON_TXT ) };
+like $@, qr/Wide character in subroutine entry/;
+
+
+@vs = eval { JSON::PP->new->utf8->incr_parse( encode 'UTF-8' => $JSON_TXT ) };
+
+ok( !$@ );
+ok( scalar @vs == 3 );
+
+is_deeply( \@vs, [ { a => "1" }, { b => "\N{BULLET}" }, { c => "3" } ] );
+is_deeply( $vs[0], { a => "1" } );
+is_deeply( $vs[1], { b => "\N{BULLET}" } );
+is_deeply( $vs[2], { c => "3" } );
+
+
+# Double-Encoded => "You Get What You Ask For"
+
+@vs = eval { JSON::PP->new->utf8->incr_parse( encode 'UTF-8' => ( encode 'UTF-8' => $JSON_TXT ) ) };
+
+ok( !$@ );
+ok( scalar @vs == 3 );
+
+is_deeply( \@vs, [ { a => "1" }, { b => "\x{E2}\x{80}\x{A2}" }, { c => "3" } ] );
+is_deeply( $vs[0], { a => "1" } );
+is_deeply( $vs[1], { b => "\x{E2}\x{80}\x{A2}" } );
+is_deeply( $vs[2], { c => "3" } );
+
+
+##########################
+### Without '->utf8' ###
+##########################
+
+@vs = eval { JSON::PP->new->incr_parse( $JSON_TXT ) };
+
+ok( !$@ );
+ok( scalar @vs == 3 );
+
+is_deeply( \@vs, [ { a => "1" }, { b => "\N{BULLET}" }, { c => "3" } ] );
+is_deeply( $vs[0], { a => "1" } );
+is_deeply( $vs[1], { b => "\N{BULLET}" } );
+is_deeply( $vs[2], { c => "3" } );
diff --git a/cpan/JSON-PP/t/120_incr_parse_truncated.t b/cpan/JSON-PP/t/120_incr_parse_truncated.t
new file mode 100644
index 0000000000..ea37ee46c2
--- /dev/null
+++ b/cpan/JSON-PP/t/120_incr_parse_truncated.t
@@ -0,0 +1,218 @@
+use strict;
+use warnings;
+use Test::More;
+use JSON::PP;
+
+plan tests => 19 * 3 + 1 * 6;
+
+sub run_test {
+ my ($input, $sub) = @_;
+ $sub->($input);
+}
+
+run_test('{"one": 1}', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok ($res, "curly braces okay -- '$input'");
+ ok (!$e, "no error -- '$input'");
+ unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error");
+});
+
+run_test('{"one": 1]', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "unbalanced curly braces -- '$input'");
+ ok ($e, "got error -- '$input'");
+ like ($e, qr/, or \} expected while parsing object\/hash/, "'} expected' json string error");
+});
+
+run_test('"', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok (!$e, "no error for input='$input'");
+ unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'");
+});
+
+run_test('{', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok (!$e, "no error for input='$input'");
+ unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'");
+});
+
+run_test('[', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok (!$e, "no error for input='$input'");
+ unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'");
+});
+
+run_test('}', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok ($e, "no error for input='$input'");
+ like ($e, qr/malformed JSON string/, "'malformed JSON string' json string error for input='$input'");
+});
+
+run_test(']', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok ($e, "no error for input='$input'");
+ like ($e, qr/malformed JSON string/, "'malformed JSON string' json string error for input='$input'");
+});
+
+run_test('1', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok ($res, "truncated input='$input'");
+ ok (!$e, "no error for input='$input'");
+ unlike ($e, qr/malformed JSON string/, "'malformed JSON string' json string error for input='$input'");
+});
+
+run_test('1', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new->allow_nonref(0);
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok ($e, "no error for input='$input'");
+ like ($e, qr/JSON text must be an object or array/, "'JSON text must be an object or array' json string error for input='$input'");
+});
+
+run_test('"1', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok (!$e, "no error for input='$input'");
+ unlike ($e, qr/malformed JSON string/, "'malformed JSON string' json string error for input='$input'");
+});
+
+run_test('\\', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok ($e, "no error for input='$input'");
+ like ($e, qr/malformed JSON string/, "'malformed JSON string' json string error for input='$input'");
+});
+
+run_test('{"one": "', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok (!$e, "no error for input='$input'");
+ unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'");
+});
+
+run_test('{"one": {', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok (!$e, "no error for input='$input'");
+ unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'");
+});
+
+run_test('{"one": [', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok (!$e, "no error for input='$input'");
+ unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'");
+});
+
+run_test('{"one": t', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok (!$e, "no error for input='$input'");
+ unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'");
+});
+
+run_test('{"one": \\', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok (!$e, "no error for input='$input'");
+ unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'");
+});
+
+run_test('{"one": ', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok (!$e, "no error for input='$input'");
+ unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'");
+});
+
+run_test('{"one": 1', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok (!$e, "no error for input='$input'");
+ unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'");
+});
+
+run_test('{"one": {"two": 2', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated '$input'");
+ ok (!$e, "no error -- '$input'");
+ unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error -- $input");
+});
+
+# Test Appending Closing '}' Curly Bracket
+run_test('{"one": 1', sub {
+ my $input = shift;
+ my $coder = JSON::PP->new;
+ my $res = eval { $coder->incr_parse($input) };
+ my $e = $@; # test more clobbers $@, we need it twice
+ ok (!$res, "truncated input='$input'");
+ ok (!$e, "no error for input='$input'");
+ unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'");
+
+ $res = eval { $coder->incr_parse('}') };
+ $e = $@; # test more clobbers $@, we need it twice
+ ok ($res, "truncated input='$input' . '}'");
+ ok (!$e, "no error for input='$input' . '}'");
+ unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input' . '}'");
+});
diff --git a/cpan/JSON-PP/t/rt_122270_old_xs_boolean.t b/cpan/JSON-PP/t/rt_122270_old_xs_boolean.t
new file mode 100644
index 0000000000..a3deb48787
--- /dev/null
+++ b/cpan/JSON-PP/t/rt_122270_old_xs_boolean.t
@@ -0,0 +1,33 @@
+# copied over from JSON::XS and modified to use JSON::PP
+
+use strict;
+use warnings;
+use Test::More;
+BEGIN { plan tests => 10 };
+
+BEGIN { $ENV{PERL_JSON_BACKEND} = 0; }
+
+use utf8;
+use JSON::PP;
+
+SKIP: {
+ skip "no JSON::XS < 3", 5 unless eval { require JSON::XS; JSON::XS->VERSION < 3 };
+
+ my $false = JSON::XS::false();
+ ok (JSON::PP::is_bool $false);
+ ok (++$false == 1);
+ ok (!JSON::PP::is_bool $false);
+ ok (!JSON::PP::is_bool "JSON::PP::Boolean");
+ ok (!JSON::PP::is_bool {}); # GH-34
+}
+
+SKIP: {
+ skip "no Types::Serialiser 0.01", 5 unless eval { require JSON::XS; JSON::XS->VERSION(3.00); require Types::Serialiser; Types::Serialiser->VERSION == 0.01 };
+
+ my $false = JSON::XS::false();
+ ok (JSON::PP::is_bool $false);
+ ok (++$false == 1);
+ ok (!JSON::PP::is_bool $false);
+ ok (!JSON::PP::is_bool "JSON::PP::Boolean");
+ ok (!JSON::PP::is_bool {}); # GH-34
+}