File Coverage

blib/lib/JSON/backportPP.pm
Criterion Covered Total %
statement 823 972 84.6
branch 487 630 77.3
condition 170 275 61.8
subroutine 134 164 81.7
pod 42 82 51.2
total 1656 2123 78.0


line stmt bran cond sub pod time code
1             package # This is JSON::backportPP
2             JSON::PP;
3              
4             # JSON-2.0
5              
6 57     57   1142 use 5.008;
  57         199  
7 57     57   306 use strict;
  57         100  
  57         1401  
8              
9 57     57   223 use Exporter ();
  57         110  
  57         1900  
10 57     57   1990 BEGIN { @JSON::backportPP::ISA = ('Exporter') }
11              
12 57     57   30152 use overload ();
  57         82922  
  57         1534  
13 57     57   20665 use JSON::backportPP::Boolean;
  57         152  
  57         1538  
14              
15 57     57   285 use Carp ();
  57         82  
  57         1080  
16 57     57   226 use Scalar::Util qw(blessed reftype refaddr);
  57         102  
  57         5472  
17             #use Devel::Peek;
18              
19             $JSON::backportPP::VERSION = '4.18';
20              
21             our @EXPORT = qw(encode_json decode_json from_json to_json);
22              
23             # instead of hash-access, i tried index-access for speed.
24             # but this method is not faster than what i expected. so it will be changed.
25              
26 57     57   289 use constant P_ASCII => 0;
  57         128  
  57         5127  
27 57     57   275 use constant P_LATIN1 => 1;
  57         77  
  57         2281  
28 57     57   204 use constant P_UTF8 => 2;
  57         498  
  57         2325  
29 57     57   383 use constant P_INDENT => 3;
  57         173  
  57         1974  
30 57     57   193 use constant P_CANONICAL => 4;
  57         116  
  57         2146  
31 57     57   224 use constant P_SPACE_BEFORE => 5;
  57         132  
  57         2147  
32 57     57   236 use constant P_SPACE_AFTER => 6;
  57         104  
  57         2171  
33 57     57   211 use constant P_ALLOW_NONREF => 7;
  57         66  
  57         2067  
34 57     57   212 use constant P_SHRINK => 8;
  57         75  
  57         1904  
35 57     57   186 use constant P_ALLOW_BLESSED => 9;
  57         96  
  57         2005  
36 57     57   197 use constant P_CONVERT_BLESSED => 10;
  57         80  
  57         1913  
37 57     57   236 use constant P_RELAXED => 11;
  57         84  
  57         1809  
38              
39 57     57   193 use constant P_LOOSE => 12;
  57         95  
  57         1894  
40 57     57   207 use constant P_ALLOW_BIGNUM => 13;
  57         125  
  57         1856  
41 57     57   180 use constant P_ALLOW_BAREKEY => 14;
  57         108  
  57         2027  
42 57     57   227 use constant P_ALLOW_SINGLEQUOTE => 15;
  57         111  
  57         1994  
43 57     57   382 use constant P_ESCAPE_SLASH => 16;
  57         132  
  57         1899  
44 57     57   198 use constant P_AS_NONBLESSED => 17;
  57         83  
  57         2299  
45              
46 57     57   257 use constant P_ALLOW_UNKNOWN => 18;
  57         70  
  57         1917  
47 57     57   190 use constant P_ALLOW_TAGS => 19;
  57         70  
  57         2609  
48              
49 57   50 57   211 use constant USE_B => $ENV{PERL_JSON_PP_USE_B} || 0;
  57         93  
  57         2710  
50 57     57   278 use constant CORE_BOOL => defined &builtin::is_bool;
  57         86  
  57         6591  
51              
52             my $invalid_char_re;
53              
54             BEGIN {
55 57     57   193 $invalid_char_re = "[";
56 57         134 for my $i (0 .. 0x01F, 0x22, 0x5c) { # '/' is ok
57 1938         2516 $invalid_char_re .= quotemeta chr utf8::unicode_to_native($i);
58             }
59              
60 57         3759 $invalid_char_re = qr/$invalid_char_re]/;
61             }
62              
63             BEGIN {
64 57     57   7142 if (USE_B) {
65             require B;
66             }
67             }
68              
69             BEGIN {
70 57     57   349 my @xs_compati_bit_properties = qw(
71             latin1 ascii utf8 indent canonical space_before space_after allow_nonref shrink
72             allow_blessed convert_blessed relaxed allow_unknown
73             allow_tags
74             );
75 57         185 my @pp_bit_properties = qw(
76             allow_singlequote allow_bignum loose
77             allow_barekey escape_slash as_nonblessed
78             );
79              
80 57         130 for my $name (@xs_compati_bit_properties, @pp_bit_properties) {
81 1140         2928 my $property_id = 'P_' . uc($name);
82              
83 1140 50   2 1 215313 eval qq/
  2 50   1 1 577  
  2 50   10 1 7  
  2 50   24647 1 7  
  0 100   1 1 0  
  2 100   0 1 6  
  1 100   3 1 3  
  1 100   0 0 3  
  1 50   12298 1 3  
  0 50   15 1 0  
  1 0   12 1 1  
  10 0   1 1 774  
  10 100   0 0 18  
  7 100   0 0 19  
  3 0   7 0 7  
  10 0   7 0 44  
  24647 100   0 0 101904  
  24647 100   0 0 71984  
  9279 100   0 0 21975  
  15368 100   0 0 34941  
  24647 100   7 0 413664  
  1 100   7 0 456  
  1 50   7 0 2  
  1 50   0 0 4  
  0 0   7 0 0  
  1 0   7 0 3  
  0 100   0 0 0  
  0 100   7 0 0  
  0 0   7 0 0  
  0 0   7 0 0  
  0 0   7 0 0  
  3 0   280 0 789  
  3 100   12 1 6  
  2 100   8 1 5  
  1 100   0 1 3  
  3 0   20 1 6  
  0 100   21510 1 0  
  0 100   13 1 0  
  0 0   12 1 0  
  0 100   18503 1 0  
  0 100       0  
  12298 100       42139  
  12298 100       40823  
  12296 100       26883  
  2 100       4  
  12298 100       77803  
  15 100       673  
  15 100       37  
  13 0       35  
  2 0       4  
  15 100       30  
  12 100       536  
  12 100       24  
  9 100       21  
  3 100       5  
  12 100       33  
  1 100       6  
  1 100       3  
  1 100       6  
  0 100       0  
  1         5  
  0         0  
  0         0  
  7         237  
  7         295  
  0         0  
  0         0  
  0         0  
  0         0  
  7         898  
  7         237  
  7         256  
  0         0  
  7         251  
  7         289  
  0         0  
  7         237  
  7         243  
  7         318  
  7         335  
  280         1220  
  12         1703  
  12         20  
  8         13  
  4         9  
  12         80  
  8         485  
  8         19  
  6         19  
  2         4  
  8         76  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  20         553  
  20         36  
  18         40  
  2         4  
  20         32  
  21510         52106  
  21510         33595  
  21508         73165  
  2         5  
  21510         69854  
  13         435  
  13         23  
  8         14  
  5         7  
  13         20  
  12         491  
  12         20  
  8         18  
  4         8  
  12         70  
  18503         47283  
  18503         34231  
  18501         31770  
  2         5  
  18503         245775  
84             sub $name {
85             my \$enable = defined \$_[1] ? \$_[1] : 1;
86              
87             if (\$enable) {
88             \$_[0]->{PROPS}->[$property_id] = 1;
89             }
90             else {
91             \$_[0]->{PROPS}->[$property_id] = 0;
92             }
93              
94             \$_[0];
95             }
96              
97             sub get_$name {
98             \$_[0]->{PROPS}->[$property_id] ? 1 : '';
99             }
100             /;
101             }
102              
103             }
104              
105              
106              
107             # Functions
108              
109             my $JSON; # cache
110              
111             sub encode_json ($) { # encode
112 185   33 185 1 889 ($JSON ||= __PACKAGE__->new->utf8)->encode(@_);
113             }
114              
115              
116             sub decode_json ($) { # decode
117 6257   66 6257 1 6633972 ($JSON ||= __PACKAGE__->new->utf8)->decode(@_);
118             }
119              
120             # Obsoleted
121              
122             sub to_json($) {
123 0     0 0 0 Carp::croak ("JSON::PP::to_json has been renamed to encode_json.");
124             }
125              
126              
127             sub from_json($) {
128 0     0 0 0 Carp::croak ("JSON::PP::from_json has been renamed to decode_json.");
129             }
130              
131              
132             # Methods
133              
134             sub new {
135 43190     43190 1 2876814 my $class = shift;
136 43190         153347 my $self = {
137             max_depth => 512,
138             max_size => 0,
139             indent_length => 3,
140             };
141              
142 43190         104480 $self->{PROPS}[P_ALLOW_NONREF] = 1;
143              
144 43190         1235361 bless $self, $class;
145             }
146              
147              
148             sub encode {
149 25125     25125 1 157206 return $_[0]->PP_encode_json($_[1]);
150             }
151              
152              
153             sub decode {
154 24984     24984 1 118338 return $_[0]->PP_decode_json($_[1], 0x00000000);
155             }
156              
157              
158             sub decode_prefix {
159 8     8 1 764 return $_[0]->PP_decode_json($_[1], 0x00000001);
160             }
161              
162              
163             # accessor
164              
165              
166             # pretty printing
167              
168             sub pretty {
169 5     5 1 3039 my ($self, $v) = @_;
170 5 50       12 my $enable = defined $v ? $v : 1;
171              
172 5 100       8 if ($enable) { # indent_length(3) for JSON::XS compatibility
173 3         68 $self->indent(1)->space_before(1)->space_after(1);
174             }
175             else {
176 2         45 $self->indent(0)->space_before(0)->space_after(0);
177             }
178              
179 5         21 $self;
180             }
181              
182             # etc
183              
184             sub max_depth {
185 7 100   7 1 23 my $max = defined $_[1] ? $_[1] : 0x80000000;
186 7         13 $_[0]->{max_depth} = $max;
187 7         37 $_[0];
188             }
189              
190              
191 358     358 0 826 sub get_max_depth { $_[0]->{max_depth}; }
192              
193              
194             sub max_size {
195 5 100   5 1 14 my $max = defined $_[1] ? $_[1] : 0;
196 5         9 $_[0]->{max_size} = $max;
197 5         12 $_[0];
198             }
199              
200              
201 322     322 0 576 sub get_max_size { $_[0]->{max_size}; }
202              
203             sub boolean_values {
204 0     0 1 0 my $self = shift;
205 0 0       0 if (@_) {
206 0         0 my ($false, $true) = @_;
207 0         0 $self->{false} = $false;
208 0         0 $self->{true} = $true;
209 0         0 if (CORE_BOOL) {
210 57     57   101293 BEGIN { CORE_BOOL and warnings->unimport(qw(experimental::builtin)) }
211 0 0 0     0 if (builtin::is_bool($true) && builtin::is_bool($false) && $true && !$false) {
      0        
      0        
212 0         0 $self->{core_bools} = !!1;
213             }
214             else {
215 0         0 delete $self->{core_bools};
216             }
217             }
218             } else {
219 0         0 delete $self->{false};
220 0         0 delete $self->{true};
221 0         0 delete $self->{core_bools};
222             }
223 0         0 return $self;
224             }
225              
226             sub core_bools {
227 0     0 1 0 my $self = shift;
228 0 0       0 my $core_bools = defined $_[0] ? $_[0] : 1;
229 0 0       0 if ($core_bools) {
230 0         0 $self->{true} = !!1;
231 0         0 $self->{false} = !!0;
232 0         0 $self->{core_bools} = !!1;
233             }
234             else {
235 0         0 $self->{true} = $JSON::PP::true;
236 0         0 $self->{false} = $JSON::PP::false;
237 0         0 $self->{core_bools} = !!0;
238             }
239 0         0 return $self;
240             }
241              
242             sub get_core_bools {
243 0     0 0 0 my $self = shift;
244 0         0 return !!$self->{core_bools};
245             }
246              
247             sub unblessed_bool {
248 0     0 0 0 my $self = shift;
249 0         0 return $self->core_bools(@_);
250             }
251              
252             sub get_unblessed_bool {
253 0     0 0 0 my $self = shift;
254 0         0 return $self->get_core_bools(@_);
255             }
256              
257             sub get_boolean_values {
258 0     0 0 0 my $self = shift;
259 0 0 0     0 if (exists $self->{true} and exists $self->{false}) {
260 0         0 return @$self{qw/false true/};
261             }
262 0         0 return;
263             }
264              
265             sub filter_json_object {
266 3 100 66 3 1 12 if (defined $_[1] and ref $_[1] eq 'CODE') {
267 2         3 $_[0]->{cb_object} = $_[1];
268             } else {
269 1         4 delete $_[0]->{cb_object};
270             }
271 3 50 66     10 $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0;
272 3         3 $_[0];
273             }
274              
275             sub filter_json_single_key_object {
276 4 50 33 4 1 22 if (@_ == 1 or @_ > 3) {
277 0         0 Carp::croak("Usage: JSON::PP::filter_json_single_key_object(self, key, callback = undef)");
278             }
279 4 100 66     13 if (defined $_[2] and ref $_[2] eq 'CODE') {
280 3         7 $_[0]->{cb_sk_object}->{$_[1]} = $_[2];
281             } else {
282 1         4 delete $_[0]->{cb_sk_object}->{$_[1]};
283 1 50       2 delete $_[0]->{cb_sk_object} unless %{$_[0]->{cb_sk_object} || {}};
  1 50       4  
284             }
285 4 50 33     9 $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0;
286 4         4 $_[0];
287             }
288              
289             sub indent_length {
290 0 0 0 0 1 0 if (!defined $_[1] or $_[1] > 15 or $_[1] < 0) {
      0        
291 0         0 Carp::carp "The acceptable range of indent_length() is 0 to 15.";
292             }
293             else {
294 0         0 $_[0]->{indent_length} = $_[1];
295             }
296 0         0 $_[0];
297             }
298              
299             sub get_indent_length {
300 0     0 0 0 $_[0]->{indent_length};
301             }
302              
303             sub sort_by {
304 3 50   3 1 1976 $_[0]->{sort_by} = defined $_[1] ? $_[1] : 1;
305 3         15 $_[0];
306             }
307              
308             sub allow_bigint {
309 0     0 0 0 Carp::carp("allow_bigint() is obsoleted. use allow_bignum() instead.");
310 0         0 $_[0]->allow_bignum;
311             }
312              
313             ###############################
314              
315             ###
316             ### Perl => JSON
317             ###
318              
319              
320             { # Convert
321              
322             sub PP_encode_json {
323 25125     25125 0 38349 my $self = shift;
324 25125         37067 my $obj = shift;
325              
326 25125         53745 $self->{indent_count} = 0;
327 25125         43903 $self->{depth} = 0;
328              
329 25125         41075 my $props = $self->{PROPS};
330              
331 25125 100   590   91390 $self->{keysort} = $self->{PROPS}[P_CANONICAL] ? sub { $a cmp $b } : undef;
  590         1358  
332              
333 25125 100       76231 if ($self->{sort_by}) {
334             $self->{keysort} = ref($self->{sort_by}) eq 'CODE' ? $self->{sort_by}
335             : $self->{sort_by} =~ /\D+/ ? $self->{sort_by}
336 3 100   22   23 : sub { $a cmp $b };
  22 100       40  
337             }
338              
339 25125 50 66     65811 encode_error("hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)")
340             if(!ref $obj and !$props->[ P_ALLOW_NONREF ]);
341              
342 25125         82565 my $str = $self->object_to_json($obj);
343              
344 25107 100       58633 $str .= "\n" if ( $self->{PROPS}[P_INDENT] ); # JSON::XS 2.26 compatible
345              
346 25107         81026 return $str;
347             }
348              
349              
350             sub object_to_json {
351 25480     25480 0 51079 my ($self, $obj) = @_;
352 25480         55389 my $type = ref($obj);
353              
354 25480 100       74248 if($type eq 'HASH'){
    100          
    100          
355 343         640 return $self->hash_to_json($obj);
356             }
357             elsif($type eq 'ARRAY'){
358 25019         68779 return $self->array_to_json($obj);
359             }
360             elsif ($type) { # blessed object?
361 54 100       110 if (blessed($obj)) {
362              
363 34 100       201 return $self->value_to_json($obj) if ( $obj->isa('JSON::PP::Boolean') );
364              
365 16 50 33     58 if ( $self->{PROPS}[P_ALLOW_TAGS] and $obj->can('FREEZE') ) {
366 0   0     0 my $obj_class = ref $obj || $obj;
367 0         0 $obj = bless $obj, $obj_class;
368 0         0 my @results = $obj->FREEZE('JSON');
369 0 0 0     0 if ( @results and ref $results[0] ) {
370 0 0       0 if ( refaddr( $obj ) eq refaddr( $results[0] ) ) {
371 0         0 encode_error( sprintf(
372             "%s::FREEZE method returned same object as was passed instead of a new one",
373             ref $obj
374             ) );
375             }
376             }
377 0         0 return '("'.$obj_class.'")['.join(',', @results).']';
378             }
379              
380 16 100 100     93 if ( $self->{PROPS}[P_CONVERT_BLESSED] and $obj->can('TO_JSON') ) {
381 8         72 my $result = $obj->TO_JSON();
382 8 100 66     48 if ( defined $result and ref( $result ) ) {
383 4 100       13 if ( refaddr( $obj ) eq refaddr( $result ) ) {
384 1         3 encode_error( sprintf(
385             "%s::TO_JSON method returned same object as was passed instead of a new one",
386             ref $obj
387             ) );
388             }
389             }
390              
391 7         69 return $self->object_to_json( $result );
392             }
393              
394 8 100 66     23 return "$obj" if ( $self->{PROPS}[P_ALLOW_BIGNUM] and _is_bignum($obj) );
395              
396 6 100       9 if ($self->{PROPS}[P_ALLOW_BLESSED]) {
397 4 50       8 return $self->blessed_to_json($obj) if ($self->{PROPS}[P_AS_NONBLESSED]); # will be removed.
398 4         9 return 'null';
399             }
400 2         10 encode_error( sprintf("encountered object '%s', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled (or TO_JSON/FREEZE method missing)", $obj)
401             );
402             }
403             else {
404 20         40 return $self->value_to_json($obj);
405             }
406             }
407             else{
408 64         143 return $self->value_to_json($obj);
409             }
410             }
411              
412              
413             sub hash_to_json {
414 343     343 0 480 my ($self, $obj) = @_;
415 343         357 my @res;
416              
417             encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)")
418 343 100       707 if (++$self->{depth} > $self->{max_depth});
419              
420 342 100       709 my ($pre, $post) = $self->{PROPS}[P_INDENT] ? $self->_up_indent() : ('', '');
421 342 100       795 my $del = ($self->{PROPS}[P_SPACE_BEFORE] ? ' ' : '') . ':' . ($self->{PROPS}[P_SPACE_AFTER] ? ' ' : '');
    100          
422              
423 342         596 for my $k ( $self->__sort( $obj ) ) {
424             push @res, $self->string_to_json( $k )
425             . $del
426 663 100       1184 . ( ref $obj->{$k} ? $self->object_to_json( $obj->{$k} ) : $self->value_to_json( $obj->{$k} ) );
427             }
428              
429 340         577 --$self->{depth};
430 340 100       524 $self->_down_indent() if ($self->{PROPS}[P_INDENT]);
431              
432 340 100       515 return '{}' unless @res;
433 330         1221 return '{' . $pre . join( ",$pre", @res ) . $post . '}';
434             }
435              
436              
437             sub array_to_json {
438 25019     25019 0 41748 my ($self, $obj) = @_;
439 25019         33543 my @res;
440              
441             encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)")
442 25019 100       65898 if (++$self->{depth} > $self->{max_depth});
443              
444 25018 100       69233 my ($pre, $post) = $self->{PROPS}[P_INDENT] ? $self->_up_indent() : ('', '');
445              
446 25018         49531 for my $v (@$obj){
447 25807 100       79150 push @res, ref($v) ? $self->object_to_json($v) : $self->value_to_json($v);
448             }
449              
450 25004         38099 --$self->{depth};
451 25004 100       40704 $self->_down_indent() if ($self->{PROPS}[P_INDENT]);
452              
453 25004 100       47737 return '[]' unless @res;
454 24994 50 66     105673 my $space = $pre eq '' && $self->{PROPS}[P_SPACE_AFTER] ? ' ' : '';
455 24994         219964 return '[' . $pre . join( ",$space$pre", @res ) . $post . ']';
456             }
457              
458             sub _looks_like_number {
459 26135     26135   38587 my $value = shift;
460 26135         38306 if (USE_B) {
461             my $b_obj = B::svref_2object(\$value);
462             my $flags = $b_obj->FLAGS;
463             return 1 if $flags & ( B::SVp_IOK() | B::SVp_NOK() ) and !( $flags & B::SVp_POK() );
464             return;
465             } else {
466 57     57   495 no warnings 'numeric';
  57         97  
  57         8649  
467             # if the utf8 flag is on, it almost certainly started as a string
468 26135 100       89527 return if utf8::is_utf8($value);
469             # detect numbers
470             # string & "" -> ""
471             # number & "" -> 0 (with warning)
472             # nan and inf can detect as numbers, so check with * 0
473 13648 100       56310 return unless length((my $dummy = "") & $value);
474 797 50       1567 return unless 0 + $value eq $value;
475 797 50       1865 return 1 if $value * 0 == 0;
476 0         0 return -1; # inf/nan
477             }
478             }
479              
480             sub value_to_json {
481 26224     26224 0 47932 my ($self, $value) = @_;
482              
483 26224 100       55448 return 'null' if(!defined $value);
484              
485 26179         42438 my $type = ref($value);
486              
487 26179 100 66     49108 if (!$type) {
    100          
488 57     57   63828 BEGIN { CORE_BOOL and warnings->unimport('experimental::builtin') }
489 26141 100       73537 if (CORE_BOOL && builtin::is_bool($value)) {
    100          
490 6 100       39 return $value ? 'true' : 'false';
491             }
492             elsif (_looks_like_number($value)) {
493 797         1921 return $value;
494             }
495 25338         74498 return $self->string_to_json($value);
496             }
497             elsif( blessed($value) and $value->isa('JSON::PP::Boolean') ){
498 18 100       138 return $$value == 1 ? 'true' : 'false';
499             }
500             else {
501 20 50       56 if ((overload::StrVal($value) =~ /=(\w+)/)[0]) {
502 0         0 return $self->value_to_json("$value");
503             }
504              
505 20 100 100     169 if ($type eq 'SCALAR' and defined $$value) {
506             return $$value eq '1' ? 'true'
507             : $$value eq '0' ? 'false'
508 7 100       50 : $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ? 'null'
    100          
    100          
509             : encode_error("cannot encode reference to scalar");
510             }
511              
512 13 100       38 if ( $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ) {
513 4         13 return 'null';
514             }
515             else {
516 9 100 100     30 if ( $type eq 'SCALAR' or $type eq 'REF' ) {
517 6         9 encode_error("cannot encode reference to scalar");
518             }
519             else {
520 3         14 encode_error("encountered $value, but JSON can only represent references to arrays or hashes");
521             }
522             }
523              
524             }
525             }
526              
527              
528             my %esc = (
529             "\n" => '\n',
530             "\r" => '\r',
531             "\t" => '\t',
532             "\f" => '\f',
533             "\b" => '\b',
534             "\"" => '\"',
535             "\\" => '\\\\',
536             "\'" => '\\\'',
537             );
538              
539              
540             sub string_to_json {
541 26001     26001 0 50749 my ($self, $arg) = @_;
542              
543 26001         446099 $arg =~ s/(["\\\n\r\t\f\b])/$esc{$1}/g;
544 26001 100       64494 $arg =~ s/\//\\\//g if ($self->{PROPS}[P_ESCAPE_SLASH]);
545              
546             # On ASCII platforms, matches [\x00-\x08\x0b\x0e-\x1f]
547 26001         119392 $arg =~ s/([^\n\t\c?[:^cntrl:][:^ascii:]])/'\\u00' . unpack('H2', $1)/eg;
  580660         1249600  
548              
549 26001 100       60151 if ($self->{PROPS}[P_ASCII]) {
550 12297         34268 $arg = _encode_ascii($arg);
551             }
552              
553 26001 100       197366 if ($self->{PROPS}[P_LATIN1]) {
554 2         5 $arg = _encode_latin1($arg);
555             }
556              
557 26001 100       52045 if ($self->{PROPS}[P_UTF8]) {
558 12545         38209 utf8::encode($arg);
559             }
560              
561 26001         249212 return '"' . $arg . '"';
562             }
563              
564              
565             sub blessed_to_json {
566 0   0 0 0 0 my $reftype = reftype($_[1]) || '';
567 0 0       0 if ($reftype eq 'HASH') {
    0          
568 0         0 return $_[0]->hash_to_json($_[1]);
569             }
570             elsif ($reftype eq 'ARRAY') {
571 0         0 return $_[0]->array_to_json($_[1]);
572             }
573             else {
574 0         0 return 'null';
575             }
576             }
577              
578              
579             sub encode_error {
580 18     18 0 26 my $error = shift;
581 18         2237 Carp::croak "$error";
582             }
583              
584              
585             sub __sort {
586 342     342   399 my $self = shift;
587 342         420 my $keysort = $self->{keysort};
588 342 100       540 defined $keysort ? (sort $keysort (keys %{$_[0]})) : keys %{$_[0]};
  222         1035  
  120         410  
589             }
590              
591              
592             sub _up_indent {
593 9     9   9 my $self = shift;
594 9         15 my $space = ' ' x $self->{indent_length};
595              
596 9         12 my ($pre,$post) = ('','');
597              
598 9         12 $post = "\n" . $space x $self->{indent_count};
599              
600 9         9 $self->{indent_count}++;
601              
602 9         12 $pre = "\n" . $space x $self->{indent_count};
603              
604 9         19 return ($pre,$post);
605             }
606              
607              
608 9     9   12 sub _down_indent { $_[0]->{indent_count}--; }
609              
610             } # Convert
611              
612              
613             sub _encode_ascii {
614             join('',
615             map {
616 12297 100   12297   268438 chr($_) =~ /[[:ascii:]]/ ?
  6264941 100       11101381  
617             chr($_) :
618             $_ <= 65535 ?
619             sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_));
620             } unpack('U*', $_[0])
621             );
622             }
623              
624              
625             sub _encode_latin1 {
626             join('',
627             map {
628 2 50   2   8 $_ <= 255 ?
  22 100       50  
629             chr($_) :
630             $_ <= 65535 ?
631             sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_));
632             } unpack('U*', $_[0])
633             );
634             }
635              
636              
637             sub _encode_surrogates { # from perlunicode
638 1127735     1127735   979583 my $uni = $_[0] - 0x10000;
639 1127735         2048610 return ($uni / 0x400 + 0xD800, $uni % 0x400 + 0xDC00);
640             }
641              
642              
643             sub _is_bignum {
644 2 100   2   11 $_[0]->isa('Math::BigInt') or $_[0]->isa('Math::BigFloat');
645             }
646              
647              
648              
649             #
650             # JSON => Perl
651             #
652              
653             my $max_intsize;
654              
655             BEGIN {
656 57     57   231 my $checkint = 1111;
657 57         203 for my $d (5..64) {
658 969         1211 $checkint .= 1;
659 969         40227 my $int = eval qq| $checkint |;
660 969 100       3574 if ($int =~ /[eE]/) {
661 57         91 $max_intsize = $d - 1;
662 57         19056 last;
663             }
664             }
665             }
666              
667             { # PARSE
668              
669             my %escapes = ( # by Jeremy Muhlich
670             b => "\b",
671             t => "\t",
672             n => "\n",
673             f => "\f",
674             r => "\r",
675             '\\' => '\\',
676             '"' => '"',
677             '/' => '/',
678             );
679              
680             sub _detect_utf_encoding {
681 12453     12453   15837 my $text = shift;
682 12453         37432 my @octets = unpack('C4', $text);
683 12453 100       27977 return 'unknown' unless defined $octets[3];
684 12438 0 100     54558 return ( $octets[0] and $octets[1]) ? 'UTF-8'
    50 66        
    50 33        
    100          
    100          
685             : (!$octets[0] and $octets[1]) ? 'UTF-16BE'
686             : (!$octets[0] and !$octets[1]) ? 'UTF-32BE'
687             : ( $octets[2] ) ? 'UTF-16LE'
688             : (!$octets[2] ) ? 'UTF-32LE'
689             : 'unknown';
690             }
691              
692             sub PP_decode_json {
693 25265     25265 0 61972 my ($self, $text, $want_offset) = @_;
694              
695 25265         100310 @$self{qw/at ch depth/} = (0, '', 0);
696              
697 25265 100 100     99868 if ( !defined $text or ref $text ) {
698 4         12 $self->_decode_error("malformed JSON string, neither array, object, number, string or atom");
699             }
700              
701 25261         46887 my $props = $self->{PROPS};
702              
703 25261 100       53835 if ( $self->{PROPS}[P_UTF8] ) {
704 12453         29491 my $encoding = _detect_utf_encoding($text);
705 12453 100 100     34230 if ($encoding ne 'UTF-8' and $encoding ne 'unknown') {
706 3         16 require Encode;
707 3         51 Encode::from_to($text, $encoding, 'utf-8');
708             } else {
709 12450 50       38228 utf8::downgrade( $text, 1 ) or Carp::croak("Wide character in subroutine entry");
710             }
711             }
712             else {
713 12808         42580 utf8::encode( $text );
714             }
715              
716 25261         70043 $self->{len} = length $text;
717 25261         52466 $self->{text} = $text;
718              
719 25261 100       62078 if ($self->{max_size} > 1) {
720 57     57   25210 use bytes;
  57         23469  
  57         309  
721 2         3 my $bytes = length $text;
722             $self->_decode_error(
723             sprintf("attempted decode of JSON text of %s bytes size, but max_size is set to %s"
724             , $bytes, $self->{max_size}), 1
725 2 100       10 ) if ($bytes > $self->{max_size});
726             }
727              
728 25260         67000 $self->_white(); # remove head white space
729              
730 25260 100       50245 $self->_decode_error("malformed JSON string, neither array, object, number, string or atom") unless defined $self->{ch}; # Is there a first character for JSON structure?
731              
732 25258         49928 my $result = $self->_value();
733              
734 25188 100 100     89591 if ( !$props->[ P_ALLOW_NONREF ] and !ref $result ) {
735 4         18 $self->_decode_error(
736             'JSON text must be an object or array (but found number, string, true, false or null,'
737             . ' use allow_nonref to allow this)', 1);
738             }
739              
740 25184 50       55797 Carp::croak('something wrong.') if $self->{len} < $self->{at}; # we won't arrive here.
741              
742 25184 100       45340 my $consumed = defined $self->{ch} ? $self->{at} - 1 : $self->{at}; # consumed JSON text length
743              
744 25184         53884 $self->_white(); # remove tail white space
745              
746 25184 100       42669 return ( $result, $consumed ) if $want_offset; # all right if decode_prefix
747              
748 24909 100       52614 $self->_decode_error("garbage after JSON object") if defined $self->{ch};
749              
750 24902         239213 $result;
751             }
752              
753              
754             sub _next_chr {
755 36714334     36714334   31918133 my $self = shift;
756 36714334 100       43963713 return $self->{ch} = undef if($self->{at} >= $self->{len});
757 36689249         52082202 $self->{ch} = substr($self->{text}, $self->{at}++, 1);
758             }
759              
760              
761             sub _value {
762 55786     55786   56871 my $self = shift;
763 55786         90500 $self->_white();
764 55786         62467 my $ch = $self->{ch};
765 55786 50       74923 return if(!defined $ch);
766 55786 100       85348 return $self->_object() if($ch eq '{');
767 53616 100       101734 return $self->_array() if($ch eq '[');
768 27329 50       47666 return $self->_tag() if($ch eq '(');
769 27329 100 66     78698 return $self->_string() if($ch eq '"' or ($self->{PROPS}[P_ALLOW_SINGLEQUOTE] and $ch eq "'"));
      100        
770 977 100 100     3712 return $self->_number() if($ch =~ /[0-9]/ or $ch eq '-');
771 86         239 return $self->_word();
772             }
773              
774             sub _string {
775 29811     29811   37416 my $self = shift;
776 29811         44304 my $utf16;
777             my $is_utf8;
778              
779 29811         28892 my $utf8_len = 0;
780              
781 29811         34397 my $s = ''; # basically UTF8 flag on
782              
783 29811         36268 my $ch = $self->{ch};
784 29811 100 66     53873 if($ch eq '"' or ($self->{PROPS}[P_ALLOW_SINGLEQUOTE] and $ch eq "'")){
      100        
785 29806         31978 my $boundChar = $ch;
786              
787 29806         38925 OUTER: while( defined($ch = $self->_next_chr()) ){
788              
789 10672549 100       13636070 if($ch eq $boundChar){
    100          
790 29791         46067 $self->_next_chr();
791              
792 29791 100       50303 if ($utf16) {
793 1         2 $self->_decode_error("missing low surrogate character in surrogate pair");
794             }
795              
796 29790 100       133423 utf8::decode($s) if($is_utf8);
797              
798 29790         120506 return $s;
799             }
800             elsif($ch eq '\\'){
801 5302021         5816658 $ch = $self->_next_chr();
802 5302021 100       7393799 if(exists $escapes{$ch}){
    100          
803 153373         218358 $s .= $escapes{$ch};
804             }
805             elsif($ch eq 'u'){ # UNICODE handling
806 5148644         4502931 my $u = '';
807              
808 5148644         5397724 for(1..4){
809 20594576         20289771 $ch = $self->_next_chr();
810 20594576 50       30758131 last OUTER if($ch !~ /[0-9a-fA-F]/);
811 20594576         19934599 $u .= $ch;
812             }
813              
814             # U+D800 - U+DBFF
815 5148644 100       8092914 if ($u =~ /^[dD][89abAB][0-9a-fA-F]{2}/) { # UTF-16 high surrogate?
    100          
816 1127737         1479599 $utf16 = $u;
817             }
818             # U+DC00 - U+DFFF
819             elsif ($u =~ /^[dD][c-fC-F][0-9a-fA-F]{2}/) { # UTF-16 low surrogate?
820 1127736 100       1326343 unless (defined $utf16) {
821 1         20 $self->_decode_error("missing high surrogate character in surrogate pair");
822             }
823 1127735         955128 $is_utf8 = 1;
824 1127735   50     1202116 $s .= _decode_surrogates($utf16, $u) || next;
825 1127735         1498026 $utf16 = undef;
826             }
827             else {
828 2893171 100       3388768 if (defined $utf16) {
829 1         3 $self->_decode_error("surrogate pair expected");
830             }
831              
832 2893170         2704229 my $hex = hex( $u );
833 2893170 50       3589998 if ( chr $u =~ /[[:^ascii:]]/ ) {
834 2893170         2516320 $is_utf8 = 1;
835 2893170   50     2898046 $s .= _decode_unicode($u) || next;
836             }
837             else {
838 0         0 $s .= chr $hex;
839             }
840             }
841              
842             }
843             else{
844 4 50       8 unless ($self->{PROPS}[P_LOOSE]) {
845 4         5 $self->{at} -= 2;
846 4         7 $self->_decode_error('illegal backslash escape sequence in string');
847             }
848 0         0 $s .= $ch;
849             }
850             }
851             else{
852              
853 5340737 100       7488868 if ( $ch =~ /[[:^ascii:]]/ ) {
854 3440092 100       4135631 unless( $ch = $self->_is_valid_utf8($ch, \$utf8_len) ) {
855 4         9 $self->{at} -= 1;
856 4         16 $self->_decode_error("malformed UTF-8 character in JSON string");
857             }
858             else {
859 3440088         3607760 $self->{at} += $utf8_len - 1;
860             }
861              
862 3440088         3264806 $is_utf8 = 1;
863             }
864              
865 5340733 50       6220281 if (!$self->{PROPS}[P_LOOSE]) {
866 5340733 100       10059547 if ($ch =~ $invalid_char_re) { # '/' ok
867 4 50 33     15 if (!$self->{PROPS}[P_RELAXED] or $ch ne "\t") {
868 4         6 $self->{at}--;
869 4         24 $self->_decode_error(sprintf "invalid character 0x%X"
870             . " encountered while parsing JSON string",
871             ord $ch);
872             }
873             }
874             }
875              
876 5340729         6472245 $s .= $ch;
877             }
878             }
879             }
880              
881 6         49 $self->_decode_error("unexpected end of string while parsing JSON string");
882             }
883              
884              
885             sub _white {
886 169700     169700   160455 my $self = shift;
887 169700         188968 my $ch = $self->{ch};
888 169700         226080 while( defined $ch ){
889 197222 100 100     576141 if($ch eq '' or $ch =~ /\A[ \t\r\n]\z/){
    50 66        
890 52590         72709 $ch = $self->_next_chr();
891             }
892             elsif($self->{PROPS}[P_RELAXED] and $ch eq '/'){
893 0         0 $ch = $self->_next_chr();
894 0 0 0     0 if(defined $ch and $ch eq '/'){
    0 0        
895 0   0     0 1 while(defined($ch = $self->_next_chr()) and $ch ne "\n" and $ch ne "\r");
      0        
896             }
897             elsif(defined $ch and $ch eq '*'){
898 0         0 $ch = $self->_next_chr();
899 0         0 while(1){
900 0 0       0 if(defined $ch){
901 0 0       0 if($ch eq '*'){
902 0 0 0     0 if(defined($ch = $self->_next_chr()) and $ch eq '/'){
903 0         0 $ch = $self->_next_chr();
904 0         0 last;
905             }
906             }
907             else{
908 0         0 $ch = $self->_next_chr();
909             }
910             }
911             else{
912 0         0 $self->_decode_error("Unterminated comment");
913             }
914             }
915 0         0 next;
916             }
917             else{
918 0         0 $self->{at}--;
919 0         0 $self->_decode_error("malformed JSON string, neither array, object, number, string or atom");
920             }
921             }
922             else{
923 144632 100 100     236570 if ($self->{PROPS}[P_RELAXED] and $ch eq '#') { # correctly?
924 9         25 pos($self->{text}) = $self->{at};
925 9         30 $self->{text} =~ /\G([^\n]*(?:\r\n|\r|\n|$))/g;
926 9         13 $self->{at} = pos($self->{text});
927 9         12 $ch = $self->_next_chr;
928 9         13 next;
929             }
930              
931 144623         167504 last;
932             }
933             }
934             }
935              
936              
937             sub _array {
938 26287     26287   30072 my $self = shift;
939 26287   50     66355 my $a = $_[0] || []; # you can use this code to use another array ref object.
940              
941             $self->_decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
942 26287 100       57992 if (++$self->{depth} > $self->{max_depth});
943              
944 26284         46635 $self->_next_chr();
945 26284         41366 $self->_white();
946              
947 26284         34088 my $ch = $self->{ch};
948 26284 100 66     63918 if(defined $ch and $ch eq ']'){
949 22         38 --$self->{depth};
950 22         58 $self->_next_chr();
951 22         72 return $a;
952             }
953             else {
954 26262         45234 while(defined($ch)){
955 27075         55986 push @$a, $self->_value();
956              
957 26508         75417 $self->_white();
958              
959 26508         39812 $ch = $self->{ch};
960 26508 100       52137 if (!defined $ch) {
961 3         7 last;
962             }
963              
964 26505 100       41691 if($ch eq ']'){
965 25688         35245 --$self->{depth};
966 25688         45139 $self->_next_chr();
967 25688         54474 return $a;
968             }
969              
970 817 100       1338 if($ch ne ','){
971 2         3 last;
972             }
973              
974 815         1422 $self->_next_chr();
975 815         1666 $self->_white();
976              
977 815         989 $ch = $self->{ch};
978 815 100 100     1814 if ($self->{PROPS}[P_RELAXED] and $ch eq ']') {
979 2         2 --$self->{depth};
980 2         13 $self->_next_chr();
981 2         3 return $a;
982             }
983              
984             }
985             }
986              
987 5 100 66     22 $self->{at}-- if defined $ch and $ch ne '';
988 5         16 $self->_decode_error(", or ] expected while parsing array");
989             }
990              
991             sub _tag {
992 0     0   0 my $self = shift;
993 0 0       0 $self->_decode_error('malformed JSON string, neither array, object, number, string or atom') unless $self->{PROPS}[P_ALLOW_TAGS];
994              
995 0         0 $self->_next_chr();
996 0         0 $self->_white();
997              
998 0         0 my $tag = $self->_value();
999 0 0       0 return unless defined $tag;
1000 0 0       0 $self->_decode_error('malformed JSON string, (tag) must be a string') if ref $tag;
1001              
1002 0         0 $self->_white();
1003              
1004 0         0 my $ch = $self->{ch};
1005 0 0 0     0 if (!defined $ch or $ch ne ')') {
1006 0         0 $self->_decode_error(') expected after tag');
1007             }
1008              
1009 0         0 $self->_next_chr();
1010 0         0 $self->_white();
1011              
1012 0         0 my $val = $self->_value();
1013 0 0       0 return unless defined $val;
1014 0 0       0 $self->_decode_error('malformed JSON string, tag value must be an array') unless ref $val eq 'ARRAY';
1015              
1016 0 0       0 if (!eval { $tag->can('THAW') }) {
  0         0  
1017 0 0       0 $self->_decode_error('cannot decode perl-object (package does not exist)') if $@;
1018 0         0 $self->_decode_error('cannot decode perl-object (package does not have a THAW method)');
1019             }
1020 0         0 $tag->THAW('JSON', @$val);
1021             }
1022              
1023             sub _object {
1024 2170     2170   2263 my $self = shift;
1025 2170   50     4585 my $o = $_[0] || {}; # you can use this code to use another hash ref object.
1026 2170         2222 my $k;
1027              
1028             $self->_decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
1029 2170 50       3491 if (++$self->{depth} > $self->{max_depth});
1030 2170         3333 $self->_next_chr();
1031 2170         3338 $self->_white();
1032              
1033 2170         2617 my $ch = $self->{ch};
1034 2170 100 66     4534 if(defined $ch and $ch eq '}'){
1035 8         21 --$self->{depth};
1036 8         26 $self->_next_chr();
1037 8 100       27 if ($self->{F_HOOK}) {
1038 1         6 return $self->__json_object_hook($o);
1039             }
1040 7         23 return $o;
1041             }
1042             else {
1043 2162         2907 while (defined $ch) {
1044 3461 100 66     7854 $k = ($self->{PROPS}[P_ALLOW_BAREKEY] and $ch ne '"' and $ch ne "'") ? $self->_bareKey() : $self->_string();
1045 3456         5738 $self->_white();
1046              
1047 3456         3716 $ch = $self->{ch};
1048 3456 100 100     7727 if(!defined $ch or $ch ne ':'){
1049 3         6 $self->{at}--;
1050 3         9 $self->_decode_error("':' expected");
1051             }
1052              
1053 3453         5256 $self->_next_chr();
1054 3453         5267 $o->{$k} = $self->_value();
1055 2936         4949 $self->_white();
1056              
1057 2936         3284 $ch = $self->{ch};
1058 2936 100       3865 last if (!defined $ch);
1059              
1060 2935 100       4778 if($ch eq '}'){
1061 1630         1814 --$self->{depth};
1062 1630         2541 $self->_next_chr();
1063 1630 100       2330 if ($self->{F_HOOK}) {
1064 8         14 return $self->__json_object_hook($o);
1065             }
1066 1622         3847 return $o;
1067             }
1068              
1069 1305 100       1919 if($ch ne ','){
1070 4         5 last;
1071             }
1072              
1073 1301         2130 $self->_next_chr();
1074 1301         2175 $self->_white();
1075              
1076 1301         1579 $ch = $self->{ch};
1077 1301 100 66     2846 if ($self->{PROPS}[P_RELAXED] and $ch eq '}') {
1078 1         1 --$self->{depth};
1079 1         3 $self->_next_chr();
1080 1 50       2 if ($self->{F_HOOK}) {
1081 0         0 return $self->__json_object_hook($o);
1082             }
1083 1         2 return $o;
1084             }
1085              
1086             }
1087              
1088             }
1089              
1090 6 100 66     53 $self->{at}-- if defined $ch and $ch ne '';
1091 6         22 $self->_decode_error(", or } expected while parsing object/hash");
1092             }
1093              
1094              
1095             sub _bareKey { # doesn't strictly follow Standard ECMA-262 3rd Edition
1096 2     2   4 my $self = shift;
1097 2         4 my $key;
1098 2         4 my $ch = $self->{ch};
1099 2         8 while($ch =~ /[\$\w[:^ascii:]]/){
1100 6         7 $key .= $ch;
1101 6         8 $ch = $self->_next_chr();
1102             }
1103 2         4 return $key;
1104             }
1105              
1106              
1107             sub _word {
1108 86     86   114 my $self = shift;
1109 86         201 my $word = substr($self->{text},$self->{at}-1,4);
1110              
1111 86 100       228 if($word eq 'true'){
    100          
    100          
1112 11         23 $self->{at} += 3;
1113 11         29 $self->_next_chr;
1114 11 50       85 return defined $self->{true} ? $self->{true} : $JSON::PP::true;
1115             }
1116             elsif($word eq 'null'){
1117 46         62 $self->{at} += 3;
1118 46         86 $self->_next_chr;
1119 46         115 return undef;
1120             }
1121             elsif($word eq 'fals'){
1122 8         22 $self->{at} += 3;
1123 8 50       31 if(substr($self->{text},$self->{at},1) eq 'e'){
1124 8         17 $self->{at}++;
1125 8         55 $self->_next_chr;
1126 8 50       42 return defined $self->{false} ? $self->{false} : $JSON::PP::false;
1127             }
1128             }
1129              
1130 21         31 $self->{at}--; # for decode_error report
1131              
1132 21 100       65 $self->_decode_error("'null' expected") if ($word =~ /^n/);
1133 20 100       44 $self->_decode_error("'true' expected") if ($word =~ /^t/);
1134 19 50       57 $self->_decode_error("'false' expected") if ($word =~ /^f/);
1135 19         53 $self->_decode_error("malformed JSON string, neither array, object, number, string or atom");
1136             }
1137              
1138              
1139             sub _number {
1140 891     891   1017 my $self = shift;
1141 891         1073 my $n = '';
1142 891         1539 my $v;
1143             my $is_dec;
1144 891         0 my $is_exp;
1145              
1146 891         1247 my $ch = $self->{ch};
1147 891 100       1408 if($ch eq '-'){
1148 41         77 $n = '-';
1149 41         472 $ch = $self->_next_chr;
1150 41 100 66     250 if (!defined $ch or $ch !~ /\d/) {
1151 1         4 $self->_decode_error("malformed number (no digits after initial minus)");
1152             }
1153             }
1154              
1155             # According to RFC4627, hex or oct digits are invalid.
1156 890 100       1507 if($ch eq '0'){
1157 81         206 my $peek = substr($self->{text},$self->{at},1);
1158 81 100       255 if($peek =~ /^[0-9a-dfA-DF]/){ # e may be valid (exponential)
1159 5         15 $self->_decode_error("malformed number (leading zero must not be followed by another digit)");
1160             }
1161 76         138 $n .= $ch;
1162 76         216 $ch = $self->_next_chr;
1163             }
1164              
1165 885   100     2915 while(defined $ch and $ch =~ /\d/){
1166 1012         1228 $n .= $ch;
1167 1012         1654 $ch = $self->_next_chr;
1168             }
1169              
1170 885 100 100     2634 if(defined $ch and $ch eq '.'){
1171 27         66 $n .= '.';
1172 27         45 $is_dec = 1;
1173              
1174 27         56 $ch = $self->_next_chr;
1175 27 100 66     203 if (!defined $ch or $ch !~ /\d/) {
1176 1         5 $self->_decode_error("malformed number (no digits after decimal point)");
1177             }
1178             else {
1179 26         52 $n .= $ch;
1180             }
1181              
1182 26   100     58 while(defined($ch = $self->_next_chr) and $ch =~ /\d/){
1183 75         141 $n .= $ch;
1184             }
1185             }
1186              
1187 884 100 100     3229 if(defined $ch and ($ch eq 'e' or $ch eq 'E')){
      100        
1188 36         54 $n .= $ch;
1189 36         47 $is_exp = 1;
1190 36         62 $ch = $self->_next_chr;
1191              
1192 36 100 100     213 if(defined($ch) and ($ch eq '+' or $ch eq '-')){
    100 100        
      100        
1193 16         47 $n .= $ch;
1194 16         34 $ch = $self->_next_chr;
1195 16 100 66     77 if (!defined $ch or $ch =~ /\D/) {
1196 2         4 $self->_decode_error("malformed number (no digits after exp sign)");
1197             }
1198 14         36 $n .= $ch;
1199             }
1200             elsif(defined($ch) and $ch =~ /\d/){
1201 18         30 $n .= $ch;
1202             }
1203             else {
1204 2         8 $self->_decode_error("malformed number (no digits after exp sign)");
1205             }
1206              
1207 32   100     61 while(defined($ch = $self->_next_chr) and $ch =~ /\d/){
1208 11         24 $n .= $ch;
1209             }
1210              
1211             }
1212              
1213 880         1155 $v .= $n;
1214              
1215 880 100 100     2124 if ($is_dec or $is_exp) {
1216 48 100       106 if ($self->{PROPS}[P_ALLOW_BIGNUM]) {
1217 1         2845 require Math::BigFloat;
1218 1         32736 return Math::BigFloat->new($v);
1219             }
1220             } else {
1221 832 100       1342 if (length $v > $max_intsize) {
1222 1 50       3 if ($self->{PROPS}[P_ALLOW_BIGNUM]) { # from Adam Sussman
1223 1         8 require Math::BigInt;
1224 1         5 return Math::BigInt->new($v);
1225             }
1226             else {
1227 0         0 return "$v";
1228             }
1229             }
1230             }
1231              
1232 878 100       2882 return $is_dec ? $v/1.0 : 0+$v;
1233             }
1234              
1235             # Compute how many bytes are in the longest legal official Unicode
1236             # character
1237             my $max_unicode_length = do {
1238 57     57   159562 no warnings 'utf8';
  57         97  
  57         53236  
1239             chr 0x10FFFF;
1240             };
1241             utf8::encode($max_unicode_length);
1242             $max_unicode_length = length $max_unicode_length;
1243              
1244             sub _is_valid_utf8 {
1245 3440092     3440092   3992103 my ($self, $ch, $utf8_len_r) = @_;
1246              
1247             # Returns undef (setting $utf8_len to 0) unless the next bytes in $text
1248             # comprise a well-formed UTF-8 encoded character, in which case,
1249             # return those bytes, setting $utf8_len to their count.
1250              
1251 3440092         4303080 my $start_point = substr($self->{text}, $self->{at} - 1);
1252              
1253             # Look no further than the maximum number of bytes in a single
1254             # character
1255 3440092         3223479 my $limit = $max_unicode_length;
1256 3440092 100       4137664 $limit = length($start_point) if $limit > length($start_point);
1257              
1258             # Find the number of bytes comprising the first character in $text
1259             # (without having to know the details of its internal representation).
1260             # This loop will iterate just once on well-formed input.
1261 3440092         3842166 while ($limit > 0) { # Until we succeed or exhaust the input
1262 4679188         4279196 my $copy = substr($start_point, 0, $limit);
1263              
1264             # decode() will return true if all bytes are valid; false
1265             # if any aren't.
1266 4679188 100       6190313 if (utf8::decode($copy)) {
1267              
1268             # Is valid: get the first character, convert back to bytes,
1269             # and return those bytes.
1270 3440088         4358540 $copy = substr($copy, 0, 1);
1271 3440088         4805062 utf8::encode($copy);
1272 3440088         3147582 $$utf8_len_r = length $copy;
1273 3440088         5269422 return substr($start_point, 0, $$utf8_len_r);
1274             }
1275              
1276             # If it didn't work, it could be that there is a full legal character
1277             # followed by a partial or malformed one. Narrow the window and
1278             # try again.
1279 1239100         1444083 $limit--;
1280             }
1281              
1282             # Failed to find a legal UTF-8 character.
1283 4         7 $$utf8_len_r = 0;
1284 4         15 return;
1285             }
1286              
1287              
1288             sub _decode_error {
1289 88     88   157 my $self = shift;
1290 88         130 my $error = shift;
1291 88         120 my $no_rep = shift;
1292 88 100       278 my $str = defined $self->{text} ? substr($self->{text}, $self->{at}) : '';
1293 88         114 my $mess = '';
1294 88         111 my $type = 'U*';
1295              
1296 88         454 for my $c ( unpack( $type, $str ) ) { # emulate pv_uni_display() ?
1297 403         551 my $chr_c = chr($c);
1298 403 50       946 $mess .= $chr_c eq '\\' ? '\\\\'
    50          
    50          
    50          
    50          
    100          
    100          
1299             : $chr_c =~ /[[:print:]]/ ? $chr_c
1300             : $chr_c eq '\a' ? '\a'
1301             : $chr_c eq '\t' ? '\t'
1302             : $chr_c eq '\n' ? '\n'
1303             : $chr_c eq '\r' ? '\r'
1304             : $chr_c eq '\f' ? '\f'
1305             : sprintf('\x{%x}', $c)
1306             ;
1307 403 100       699 if ( length $mess >= 20 ) {
1308 10         13 $mess .= '...';
1309 10         20 last;
1310             }
1311             }
1312              
1313 88 100       226 unless ( length $mess ) {
1314 26         44 $mess = '(end of string)';
1315             }
1316              
1317             Carp::croak (
1318 88 100       37247 $no_rep ? "$error" : "$error, at character offset $self->{at} (before \"$mess\")"
1319             );
1320              
1321             }
1322              
1323              
1324             sub __json_object_hook {
1325 9     9   8 my $self = shift;
1326 9         9 my $o = $_[0];
1327 9         10 my @ks = keys %{$o};
  9         19  
1328              
1329 9 100 66     35 if ( $self->{cb_sk_object} and @ks == 1 and exists $self->{cb_sk_object}{ $ks[0] } and ref $self->{cb_sk_object}{ $ks[0] } ) {
      100        
      66        
1330 4         12 my @val = $self->{cb_sk_object}{ $ks[0] }->( $o->{$ks[0]} );
1331 4 100       14 if (@val == 0) {
    50          
1332 1         4 return $o;
1333             }
1334             elsif (@val == 1) {
1335 3         11 return $val[0];
1336             }
1337             else {
1338 0         0 Carp::croak("filter_json_single_key_object callbacks must not return more than one scalar");
1339             }
1340             }
1341              
1342 5 100       23 my @val = $self->{cb_object}->($o) if ($self->{cb_object});
1343 5 100       15 if (@val == 0) {
    50          
1344 3         9 return $o;
1345             }
1346             elsif (@val == 1) {
1347 2         7 return $val[0];
1348             }
1349             else {
1350 0         0 Carp::croak("filter_json_object callbacks must not return more than one scalar");
1351             }
1352             }
1353              
1354             } # PARSE
1355              
1356              
1357             sub _decode_surrogates { # from perlunicode
1358 1127735     1127735   1370387 my $uni = 0x10000 + (hex($_[0]) - 0xD800) * 0x400 + (hex($_[1]) - 0xDC00);
1359 1127735         1413690 my $un = pack('U*', $uni);
1360 1127735         1556030 utf8::encode( $un );
1361 1127735         1608582 return $un;
1362             }
1363              
1364              
1365             sub _decode_unicode {
1366 2893170     2893170   3663200 my $un = pack('U', hex shift);
1367 2893170         3892239 utf8::encode( $un );
1368 2893170         5357381 return $un;
1369             }
1370              
1371             sub incr_parse {
1372 637     637 1 37264 local $Carp::CarpLevel = 1;
1373 637   66     1752 ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_parse( @_ );
1374             }
1375              
1376              
1377             sub incr_skip {
1378 2   33 2 1 963 ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_skip;
1379             }
1380              
1381              
1382             sub incr_reset {
1383 0   0 0 1 0 ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_reset;
1384             }
1385              
1386             sub incr_text : lvalue {
1387 293   33 293 1 33643 $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new;
1388              
1389 293 50       597 if ( $_[0]->{_incr_parser}->{incr_pos} ) {
1390 0         0 Carp::croak("incr_text cannot be called when the incremental parser already started parsing");
1391             }
1392 293         1643 $_[0]->{_incr_parser}->{incr_text};
1393             }
1394              
1395              
1396             ###############################
1397             # Utilities
1398             #
1399              
1400             # shamelessly copied and modified from JSON::XS code.
1401              
1402             $JSON::PP::true = do { bless \(my $dummy = 1), "JSON::PP::Boolean" };
1403             $JSON::PP::false = do { bless \(my $dummy = 0), "JSON::PP::Boolean" };
1404              
1405             sub is_bool {
1406 5 100   5 1 23 if (blessed $_[0]) {
1407             return (
1408 2   33     23 $_[0]->isa("JSON::PP::Boolean")
1409             or $_[0]->isa("Types::Serialiser::BooleanBase")
1410             or $_[0]->isa("JSON::XS::Boolean")
1411             );
1412             }
1413             elsif (CORE_BOOL) {
1414 57     57   7333 BEGIN { CORE_BOOL and warnings->unimport('experimental::builtin') }
1415 3         15 return builtin::is_bool($_[0]);
1416             }
1417 0         0 return !!0;
1418             }
1419              
1420 0     0 1 0 sub true { $JSON::PP::true }
1421 0     0 1 0 sub false { $JSON::PP::false }
1422 0     0 1 0 sub null { undef; }
1423              
1424             ###############################
1425              
1426             package # hide from PAUSE
1427             JSON::PP::IncrParser;
1428              
1429 57     57   392 use strict;
  57         95  
  57         1752  
1430              
1431 57     57   290 use constant INCR_M_WS => 0; # initial whitespace skipping
  57         134  
  57         3859  
1432 57     57   259 use constant INCR_M_STR => 1; # inside string
  57         110  
  57         2831  
1433 57     57   248 use constant INCR_M_BS => 2; # inside backslash
  57         99  
  57         2157  
1434 57     57   215 use constant INCR_M_JSON => 3; # outside anything, count nesting
  57         95  
  57         2057  
1435 57     57   191 use constant INCR_M_C0 => 4;
  57         77  
  57         2471  
1436 57     57   242 use constant INCR_M_C1 => 5;
  57         115  
  57         2334  
1437 57     57   239 use constant INCR_M_TFN => 6;
  57         92  
  57         2229  
1438 57     57   218 use constant INCR_M_NUM => 7;
  57         89  
  57         15561  
1439              
1440             $JSON::backportPP::VERSION = '1.01';
1441              
1442             sub new {
1443 26     26   39 my ( $class ) = @_;
1444              
1445 26         149 bless {
1446             incr_nest => 0,
1447             incr_text => undef,
1448             incr_pos => 0,
1449             incr_mode => 0,
1450             }, $class;
1451             }
1452              
1453              
1454             sub incr_parse {
1455 637     637   924 my ( $self, $coder, $text ) = @_;
1456              
1457 637 100       1163 $self->{incr_text} = '' unless ( defined $self->{incr_text} );
1458              
1459 637 100       898 if ( defined $text ) {
1460 329         572 $self->{incr_text} .= $text;
1461             }
1462              
1463 637 100       1477 if ( defined wantarray ) {
1464 319         668 my $max_size = $coder->get_max_size;
1465 319         486 my $p = $self->{incr_pos};
1466 319         333 my @ret;
1467             {
1468 319         348 do {
  319         346  
1469 321 100 100     1082 unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) {
1470 320         752 $self->_incr_parse( $coder );
1471              
1472 319 100 100     562 if ( $max_size and $self->{incr_pos} > $max_size ) {
1473 1         130 Carp::croak("attempted decode of JSON text of $self->{incr_pos} bytes size, but max_size is set to $max_size");
1474             }
1475 318 100 100     827 unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) {
1476             # as an optimisation, do not accumulate white space in the incr buffer
1477 46 100 100     115 if ( $self->{incr_mode} == INCR_M_WS and $self->{incr_pos} ) {
1478 4         5 $self->{incr_pos} = 0;
1479 4         5 $self->{incr_text} = '';
1480             }
1481 46         67 last;
1482             }
1483             }
1484              
1485 273 50       7028 unless ( $coder->get_utf8 ) {
1486 273         699 utf8::decode( $self->{incr_text} );
1487             }
1488              
1489 273         719 my ($obj, $offset) = $coder->PP_decode_json( $self->{incr_text}, 0x00000001 );
1490 269         372 push @ret, $obj;
1491 57     57   322 use bytes;
  57         88  
  57         261  
1492 269   50     574 $self->{incr_text} = substr( $self->{incr_text}, $offset || 0 );
1493 269         307 $self->{incr_pos} = 0;
1494 269         275 $self->{incr_nest} = 0;
1495 269         321 $self->{incr_mode} = 0;
1496 269 100       465 last unless wantarray;
1497             } while ( wantarray );
1498             }
1499              
1500 313 100       392 if ( wantarray ) {
1501 4         21 return @ret;
1502             }
1503             else { # in scalar context
1504 309 100       1013 return defined $ret[0] ? $ret[0] : undef;
1505             }
1506             }
1507             }
1508              
1509              
1510             sub _incr_parse {
1511 320     320   402 my ($self, $coder) = @_;
1512 320         475 my $text = $self->{incr_text};
1513 320         405 my $len = length $text;
1514 320         470 my $p = $self->{incr_pos};
1515              
1516             INCR_PARSE:
1517 320         525 while ( $len > $p ) {
1518 2550         2892 my $s = substr( $text, $p, 1 );
1519 2550 50       3255 last INCR_PARSE unless defined $s;
1520 2550         2703 my $mode = $self->{incr_mode};
1521              
1522 2550 100 100     7533 if ( $mode == INCR_M_WS ) {
    50          
    100          
    100          
    100          
    100          
    50          
1523 284         378 while ( $len > $p ) {
1524 516         569 $s = substr( $text, $p, 1 );
1525 516 50       676 last INCR_PARSE unless defined $s;
1526 516 100       701 if ( ord($s) > ord " " ) {
1527 280 100       394 if ( $s eq '#' ) {
1528 6         6 $self->{incr_mode} = INCR_M_C0;
1529 6         10 redo INCR_PARSE;
1530             } else {
1531 274         306 $self->{incr_mode} = INCR_M_JSON;
1532 274         464 redo INCR_PARSE;
1533             }
1534             }
1535 236         304 $p++;
1536             }
1537             } elsif ( $mode == INCR_M_BS ) {
1538 0         0 $p++;
1539 0         0 $self->{incr_mode} = INCR_M_STR;
1540 0         0 redo INCR_PARSE;
1541             } elsif ( $mode == INCR_M_C0 or $mode == INCR_M_C1 ) {
1542 9         14 while ( $len > $p ) {
1543 45         39 $s = substr( $text, $p, 1 );
1544 45 50       47 last INCR_PARSE unless defined $s;
1545 45 100       50 if ( $s eq "\n" ) {
1546 9 100       16 $self->{incr_mode} = $self->{incr_mode} == INCR_M_C0 ? INCR_M_WS : INCR_M_JSON;
1547 9         11 last;
1548             }
1549 36         39 $p++;
1550             }
1551 9         11 next;
1552             } elsif ( $mode == INCR_M_TFN ) {
1553 35 0 33     60 last INCR_PARSE if $p >= $len && $self->{incr_nest};
1554 35         50 while ( $len > $p ) {
1555 140         154 $s = substr( $text, $p++, 1 );
1556 140 100 66     377 next if defined $s and $s =~ /[rueals]/;
1557 35         38 last;
1558             }
1559 35         35 $p--;
1560 35         51 $self->{incr_mode} = INCR_M_JSON;
1561              
1562 35 50       45 last INCR_PARSE unless $self->{incr_nest};
1563 35         54 redo INCR_PARSE;
1564             } elsif ( $mode == INCR_M_NUM ) {
1565 380 0 33     526 last INCR_PARSE if $p >= $len && $self->{incr_nest};
1566 380         510 while ( $len > $p ) {
1567 391         432 $s = substr( $text, $p++, 1 );
1568 391 100 66     1068 next if defined $s and $s =~ /[0-9eE.+\-]/;
1569 375         377 last;
1570             }
1571 380         406 $p--;
1572 380         456 $self->{incr_mode} = INCR_M_JSON;
1573              
1574 380 100       551 last INCR_PARSE unless $self->{incr_nest};
1575 375         403 redo INCR_PARSE;
1576             } elsif ( $mode == INCR_M_STR ) {
1577 585         738 while ( $len > $p ) {
1578 2063         2019 $s = substr( $text, $p, 1 );
1579 2063 50       2360 last INCR_PARSE unless defined $s;
1580 2063 100       2848 if ( $s eq '"' ) {
    100          
1581 583         507 $p++;
1582 583         574 $self->{incr_mode} = INCR_M_JSON;
1583              
1584 583 100       752 last INCR_PARSE unless $self->{incr_nest};
1585 568         549 redo INCR_PARSE;
1586             }
1587             elsif ( $s eq '\\' ) {
1588 498         463 $p++;
1589 498 50       678 if ( !defined substr($text, $p, 1) ) {
1590 0         0 $self->{incr_mode} = INCR_M_BS;
1591 0         0 last INCR_PARSE;
1592             }
1593             }
1594 1480         1767 $p++;
1595             }
1596             } elsif ( $mode == INCR_M_JSON ) {
1597 1257         1596 while ( $len > $p ) {
1598 3126         3506 $s = substr( $text, $p++, 1 );
1599 3126 50 33     13517 if ( $s eq "\x00" ) {
    100 66        
    100 100        
    100 100        
    100          
    100          
    100          
    100          
1600 0         0 $p--;
1601 0         0 last INCR_PARSE;
1602             } elsif ( $s =~ /^[\t\n\r ]$/) {
1603 682 50       974 if ( !$self->{incr_nest} ) {
1604 0         0 $p--; # do not eat the whitespace, let the next round do it
1605 0         0 last INCR_PARSE;
1606             }
1607 682         875 next;
1608             } elsif ( $s eq 't' or $s eq 'f' or $s eq 'n' ) {
1609 35         40 $self->{incr_mode} = INCR_M_TFN;
1610 35         39 redo INCR_PARSE;
1611             } elsif ( $s =~ /^[0-9\-]$/ ) {
1612 380         426 $self->{incr_mode} = INCR_M_NUM;
1613 380         459 redo INCR_PARSE;
1614             } elsif ( $s eq '"' ) {
1615 583         607 $self->{incr_mode} = INCR_M_STR;
1616 583         627 redo INCR_PARSE;
1617             } elsif ( $s eq '[' or $s eq '{' ) {
1618 355 100       680 if ( ++$self->{incr_nest} > $coder->get_max_depth ) {
1619 1         106 Carp::croak('json text or perl structure exceeds maximum nesting level (max_depth set too low?)');
1620             }
1621 354         579 next;
1622             } elsif ( $s eq ']' or $s eq '}' ) {
1623 352 100       542 if ( --$self->{incr_nest} <= 0 ) {
1624 253         382 last INCR_PARSE;
1625             }
1626             } elsif ( $s eq '#' ) {
1627 3         4 $self->{incr_mode} = INCR_M_C1;
1628 3         5 redo INCR_PARSE;
1629             }
1630             }
1631             }
1632             }
1633              
1634 319         367 $self->{incr_pos} = $p;
1635 319 100       601 $self->{incr_parsing} = $p ? 1 : 0; # for backward compatibility
1636             }
1637              
1638              
1639             sub incr_text {
1640 0 0   0   0 if ( $_[0]->{incr_pos} ) {
1641 0         0 Carp::croak("incr_text cannot be called when the incremental parser already started parsing");
1642             }
1643 0         0 $_[0]->{incr_text};
1644             }
1645              
1646              
1647             sub incr_skip {
1648 2     2   4 my $self = shift;
1649 2         6 $self->{incr_text} = substr( $self->{incr_text}, $self->{incr_pos} );
1650 2         3 $self->{incr_pos} = 0;
1651 2         2 $self->{incr_mode} = 0;
1652 2         5 $self->{incr_nest} = 0;
1653             }
1654              
1655              
1656             sub incr_reset {
1657 0     0     my $self = shift;
1658 0           $self->{incr_text} = undef;
1659 0           $self->{incr_pos} = 0;
1660 0           $self->{incr_mode} = 0;
1661 0           $self->{incr_nest} = 0;
1662             }
1663              
1664             ###############################
1665              
1666              
1667             1;
1668             __END__