Subject: | Possible inconsistencies using incr_text and incr_parsing |
Hi,
I've only noticed this whilst trying to find an issue in JSON::XS so I'm
not sure how much you will care about this. The pod for JSON::PP (and
XS) says under incr_text:
"This only works when a preceding call to incr_parse in scalar context
successfully returned an object."
The problem I'm having with JSON::XS is I call incr_text AFTER a scalar
context call to incr_parse returns an object and all is ok UNLESS the
string to parse contains unicode in which case I get:
"incr_text can not be called when the incremental parser already started
parsing"
I came across JSON::PP and thought I'd see if it worked with JSON:PP or
if JSON::PP had the same issue - it didn't but I think there may be a
small issue in JSON::PP with the use of the object attribute
"incr_parsing". It looks as if this is used to keep track of whether you
are in the middle of an incremental parse or not but the code in
incr_parse for a scalar context call does:
else { # in scalar context
$self->{incr_parsing} = 1;
my $obj = $self->_incr_parse( $coder, $self->{incr_text} );
$self->{incr_parsing} = 0;
return $obj;
}
That is it indiscriminately clears incr_parsing whether an object was
returned or not. This also means the error in incr_text:
sub incr_text {
if ( $_[0]->{incr_parsing} ) {
Carp::croak("incr_text can not be called when the incremental
parser already started parsing");
}
can never be reached. I believe incr_parse should really be:
else { # in scalar context
$self->{incr_parsing} = 1;
my $obj = $self->_incr_parse( $coder, $self->{incr_text} );
$self->{incr_parsing} = 0 if $obj; # <--- NOTE
return $obj;
}
Anyway it depends on whether the pod is right or the code was written to
protect the caller from calling incr_text in the middle of a parse.
Attached is a small self contained test.
Martin
--
Martin J. Evans
Wetherby, UK
Subject: | json_pp_incremental.pl |
use Data::Dumper;
use JSON::PP;
binmode(STDOUT, ":utf8");
my $data = ["\x{53f0}\x{6240}\x{306e}\x{6d41}\x{3057}",
"\x{6c60}\x{306e}\x{30ab}\x{30a8}\x{30eb}"];
# the following works:
#my $data = ["fred",
# "blog"];
my $j = new JSON::PP;
my $js = $j->encode($data);
$j = undef;
print "encoded: " . $js, "\n";
my @parts = (substr($js, 0, int(length($js) / 2)),
substr($js, int(length($js) / 2)));
my $j = JSON::PP->new;
my $object = $j->incr_parse($parts[0]);
die "got object" if $object;
print $j->{incr_parsing} , "\n";
eval {
print "incr_text is : " . $j->incr_text, "\n";
};
print "According to docs I'd expect incr_text to fail here - error was $@\n";
my $object = $j->incr_parse($parts[1]);
die "no object" if !$object;
print $j->{incr_parsing} , "\n";
print Dumper($object);
eval {
print "incr_text is : " . $j->incr_text;
};
print "Why do we get this error - $@" if $@;