File Coverage

blib/lib/JSON/PP.pm
Criterion Covered Total %
statement 854 968 88.2
branch 467 622 75.0
condition 181 263 68.8
subroutine 131 164 79.8
pod 42 82 51.2
total 1675 2099 79.8


line stmt bran cond sub pod time code
1             package JSON::PP;
2              
3             # JSON-2.0
4              
5 65     65   4247432 use 5.008;
  65         686  
6 65     65   371 use strict;
  65         143  
  65         1529  
7              
8 65     65   364 use Exporter ();
  65         124  
  65         2436  
9 65     65   2662 BEGIN { our @ISA = ('Exporter') }
10              
11 65     65   62887 use overload ();
  65         51265  
  65         1730  
12 65     65   27467 use JSON::PP::Boolean;
  65         170  
  65         1787  
13              
14 65     65   432 use Carp ();
  65         134  
  65         1257  
15 65     65   316 use Scalar::Util qw(blessed reftype refaddr);
  65         149  
  65         6567  
16             #use Devel::Peek;
17              
18             our $VERSION = '4.17_01';
19              
20             our @EXPORT = qw(encode_json decode_json from_json to_json);
21              
22             # instead of hash-access, i tried index-access for speed.
23             # but this method is not faster than what i expected. so it will be changed.
24              
25 65     65   497 use constant P_ASCII => 0;
  65         192  
  65         7757  
26 65     65   433 use constant P_LATIN1 => 1;
  65         163  
  65         4089  
27 65     65   480 use constant P_UTF8 => 2;
  65         130  
  65         3368  
28 65     65   393 use constant P_INDENT => 3;
  65         127  
  65         3582  
29 65     65   540 use constant P_CANONICAL => 4;
  65         174  
  65         3282  
30 65     65   363 use constant P_SPACE_BEFORE => 5;
  65         128  
  65         3418  
31 65     65   403 use constant P_SPACE_AFTER => 6;
  65         129  
  65         3255  
32 65     65   404 use constant P_ALLOW_NONREF => 7;
  65         188  
  65         3437  
33 65     65   368 use constant P_SHRINK => 8;
  65         158  
  65         3405  
34 65     65   417 use constant P_ALLOW_BLESSED => 9;
  65         164  
  65         4085  
35 65     65   1341 use constant P_CONVERT_BLESSED => 10;
  65         182  
  65         3163  
36 65     65   380 use constant P_RELAXED => 11;
  65         110  
  65         2956  
37              
38 65     65   489 use constant P_LOOSE => 12;
  65         137  
  65         3148  
39 65     65   397 use constant P_ALLOW_BIGNUM => 13;
  65         115  
  65         3301  
40 65     65   397 use constant P_ALLOW_BAREKEY => 14;
  65         116  
  65         3117  
41 65     65   611 use constant P_ALLOW_SINGLEQUOTE => 15;
  65         212  
  65         3471  
42 65     65   415 use constant P_ESCAPE_SLASH => 16;
  65         140  
  65         3410  
43 65     65   399 use constant P_AS_NONBLESSED => 17;
  65         138  
  65         3160  
44              
45 65     65   380 use constant P_ALLOW_UNKNOWN => 18;
  65         120  
  65         3444  
46 65     65   417 use constant P_ALLOW_TAGS => 19;
  65         120  
  65         4036  
47              
48 65   50 65   560 use constant USE_B => $ENV{PERL_JSON_PP_USE_B} || 0;
  65         194  
  65         4527  
49 65     65   419 use constant CORE_BOOL => defined &builtin::is_bool;
  65         132  
  65         8719  
50              
51             my $invalid_char_re;
52              
53             BEGIN {
54 65     65   283 $invalid_char_re = "[";
55 65         202 for my $i (0 .. 0x01F, 0x22, 0x5c) { # '/' is ok
56 2210         3606 $invalid_char_re .= quotemeta chr utf8::unicode_to_native($i);
57             }
58              
59 65         3815 $invalid_char_re = qr/$invalid_char_re]/;
60             }
61              
62             BEGIN {
63 65     65   7819 if (USE_B) {
64             require B;
65             }
66             }
67              
68             BEGIN {
69 65     65   489 my @xs_compati_bit_properties = qw(
70             latin1 ascii utf8 indent canonical space_before space_after allow_nonref shrink
71             allow_blessed convert_blessed relaxed allow_unknown
72             allow_tags
73             );
74 65         184 my @pp_bit_properties = qw(
75             allow_singlequote allow_bignum loose
76             allow_barekey escape_slash as_nonblessed
77             );
78              
79 65         192 for my $name (@xs_compati_bit_properties, @pp_bit_properties) {
80 1300         5356 my $property_id = 'P_' . uc($name);
81              
82 1300 50   2 1 205955 eval qq/
  2 50   1 1 987  
  2 50   2 1 6  
  2 50   24653 1 8  
  0 50   1 1 0  
  2 50   1 1 6  
  1 100   3 1 5  
  1 100   0 0 3  
  1 50   12292 1 5  
  0 50   10 1 0  
  1 50   5 1 2  
  2 50   1 1 478  
  2 100   0 0 21  
  2 100   0 0 8  
  0 0   0 0 0  
  2 0   0 0 6  
  24653 100   0 0 101437  
  24653 50   0 0 52475  
  9286 100   0 0 23553  
  15367 50   0 0 31890  
  24653 50   0 0 417508  
  1 50   0 0 598  
  1 50   0 0 3  
  1 50   0 0 4  
  0 0   0 0 0  
  1 0   0 0 2  
  1 0   0 0 4  
  1 0   0 0 3  
  1 0   0 0 4  
  0 0   0 0 0  
  1 0   0 0 19  
  3 0   309 0 863  
  3 0   6 1 11  
  2 0   2 1 5  
  1 0   0 1 3  
  3 0   14 1 7  
  0 0   21504 1 0  
  0 0   7 1 0  
  0 0   6 1 0  
  0 0   18467 1 0  
  0 0       0  
  12292 0       41559  
  12292 0       26695  
  12292 100       24996  
  0 50       0  
  12292 100       89619  
  10 50       212  
  10 50       29  
  10 0       33  
  0 0       0  
  10 50       27  
  5 50       31  
  5 50       19  
  5 50       30  
  0 50       0  
  5 100       51  
  1 50       6  
  1 100       3  
  1 100       3  
  0 50       0  
  1         5  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  309         1479  
  6         532  
  6         17  
  4         12  
  2         5  
  6         88  
  2         11  
  2         6  
  2         14  
  0         0  
  2         38  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  14         49  
  14         32  
  14         46  
  0         0  
  14         29  
  21504         69894  
  21504         43480  
  21504         54029  
  0         0  
  21504         82930  
  7         26  
  7         17  
  4         8  
  3         5  
  7         15  
  6         21  
  6         14  
  4         9  
  2         5  
  6         85  
  18467         60909  
  18467         37078  
  18467         37129  
  0         0  
  18467         288335  
83             sub $name {
84             my \$enable = defined \$_[1] ? \$_[1] : 1;
85              
86             if (\$enable) {
87             \$_[0]->{PROPS}->[$property_id] = 1;
88             }
89             else {
90             \$_[0]->{PROPS}->[$property_id] = 0;
91             }
92              
93             \$_[0];
94             }
95              
96             sub get_$name {
97             \$_[0]->{PROPS}->[$property_id] ? 1 : '';
98             }
99             /;
100             }
101              
102             }
103              
104              
105              
106             # Functions
107              
108             my $JSON; # cache
109              
110             sub encode_json ($) { # encode
111 189   66 189 1 1177 ($JSON ||= __PACKAGE__->new->utf8)->encode(@_);
112             }
113              
114              
115             sub decode_json { # decode
116 6206   66 6206 1 78808 ($JSON ||= __PACKAGE__->new->utf8)->decode(@_);
117             }
118              
119             # Obsoleted
120              
121             sub to_json($) {
122 0     0 0 0 Carp::croak ("JSON::PP::to_json has been renamed to encode_json.");
123             }
124              
125              
126             sub from_json($) {
127 0     0 0 0 Carp::croak ("JSON::PP::from_json has been renamed to decode_json.");
128             }
129              
130              
131             # Methods
132              
133             sub new {
134 43176     43176 1 2019925 my $class = shift;
135 43176         133424 my $self = {
136             max_depth => 512,
137             max_size => 0,
138             indent_length => 3,
139             };
140              
141 43176         106391 $self->{PROPS}[P_ALLOW_NONREF] = 1;
142              
143 43176         1071834 bless $self, $class;
144             }
145              
146              
147             sub encode {
148 25146     25146 1 144793 return $_[0]->PP_encode_json($_[1]);
149             }
150              
151              
152             sub decode {
153 24952     24952 1 129520 return $_[0]->PP_decode_json($_[1], 0x00000000);
154             }
155              
156              
157             sub decode_prefix {
158 8     8 1 942 return $_[0]->PP_decode_json($_[1], 0x00000001);
159             }
160              
161              
162             # accessor
163              
164              
165             # pretty printing
166              
167             sub pretty {
168 5     5 1 3006 my ($self, $v) = @_;
169 5 50       14 my $enable = defined $v ? $v : 1;
170              
171 5 100       11 if ($enable) { # indent_length(3) for JSON::XS compatibility
172 3         71 $self->indent(1)->space_before(1)->space_after(1);
173             }
174             else {
175 2         48 $self->indent(0)->space_before(0)->space_after(0);
176             }
177              
178 5         13 $self;
179             }
180              
181             # etc
182              
183             sub max_depth {
184 5 50   5 1 1353 my $max = defined $_[1] ? $_[1] : 0x80000000;
185 5         15 $_[0]->{max_depth} = $max;
186 5         39 $_[0];
187             }
188              
189              
190 383     383 0 874 sub get_max_depth { $_[0]->{max_depth}; }
191              
192              
193             sub max_size {
194 3 50   3 1 478 my $max = defined $_[1] ? $_[1] : 0;
195 3         10 $_[0]->{max_size} = $max;
196 3         10 $_[0];
197             }
198              
199              
200 383     383 0 680 sub get_max_size { $_[0]->{max_size}; }
201              
202             sub boolean_values {
203 6     6 1 1859 my $self = shift;
204 6 100       18 if (@_) {
205 4         11 my ($false, $true) = @_;
206 4         12 $self->{false} = $false;
207 4         8 $self->{true} = $true;
208 4         7 if (CORE_BOOL) {
209 65     65   123409 BEGIN { CORE_BOOL and warnings->unimport(qw(experimental::builtin)) }
210             if (builtin::is_bool($true) && builtin::is_bool($false) && $true && !$false) {
211             $self->{core_bools} = !!1;
212             }
213             else {
214             delete $self->{core_bools};
215             }
216             }
217             } else {
218 2         5 delete $self->{false};
219 2         6 delete $self->{true};
220 2         4 delete $self->{core_bools};
221             }
222 6         21 return $self;
223             }
224              
225             sub core_bools {
226 1     1 1 4 my $self = shift;
227 1 50       4 my $core_bools = defined $_[0] ? $_[0] : 1;
228 1 50       3 if ($core_bools) {
229 1         3 $self->{true} = !!1;
230 1         2 $self->{false} = !!0;
231 1         2 $self->{core_bools} = !!1;
232             }
233             else {
234 0         0 $self->{true} = $JSON::PP::true;
235 0         0 $self->{false} = $JSON::PP::false;
236 0         0 $self->{core_bools} = !!0;
237             }
238 1         3 return $self;
239             }
240              
241             sub get_core_bools {
242 3     3 0 10 my $self = shift;
243 3         16 return !!$self->{core_bools};
244             }
245              
246             sub unblessed_bool {
247 0     0 0 0 my $self = shift;
248 0         0 return $self->core_bools(@_);
249             }
250              
251             sub get_unblessed_bool {
252 0     0 0 0 my $self = shift;
253 0         0 return $self->get_core_bools(@_);
254             }
255              
256             sub get_boolean_values {
257 5     5 0 2818 my $self = shift;
258 5 50 66     30 if (exists $self->{true} and exists $self->{false}) {
259 3         12 return @$self{qw/false true/};
260             }
261 2         16 return;
262             }
263              
264             sub filter_json_object {
265 3 100 66 3 1 18 if (defined $_[1] and ref $_[1] eq 'CODE') {
266 2         7 $_[0]->{cb_object} = $_[1];
267             } else {
268 1         4 delete $_[0]->{cb_object};
269             }
270 3 50 66     13 $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0;
271 3         5 $_[0];
272             }
273              
274             sub filter_json_single_key_object {
275 4 50 33 4 1 22 if (@_ == 1 or @_ > 3) {
276 0         0 Carp::croak("Usage: JSON::PP::filter_json_single_key_object(self, key, callback = undef)");
277             }
278 4 100 66     16 if (defined $_[2] and ref $_[2] eq 'CODE') {
279 3         11 $_[0]->{cb_sk_object}->{$_[1]} = $_[2];
280             } else {
281 1         5 delete $_[0]->{cb_sk_object}->{$_[1]};
282 1 50       3 delete $_[0]->{cb_sk_object} unless %{$_[0]->{cb_sk_object} || {}};
  1 50       5  
283             }
284 4 50 33     24 $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0;
285 4         18 $_[0];
286             }
287              
288             sub indent_length {
289 0 0 0 0 1 0 if (!defined $_[1] or $_[1] > 15 or $_[1] < 0) {
      0        
290 0         0 Carp::carp "The acceptable range of indent_length() is 0 to 15.";
291             }
292             else {
293 0         0 $_[0]->{indent_length} = $_[1];
294             }
295 0         0 $_[0];
296             }
297              
298             sub get_indent_length {
299 0     0 0 0 $_[0]->{indent_length};
300             }
301              
302             sub sort_by {
303 3 50   3 1 1430 $_[0]->{sort_by} = defined $_[1] ? $_[1] : 1;
304 3         15 $_[0];
305             }
306              
307             sub allow_bigint {
308 0     0 0 0 Carp::carp("allow_bigint() is obsoleted. use allow_bignum() instead.");
309 0         0 $_[0]->allow_bignum;
310             }
311              
312             ###############################
313              
314             ###
315             ### Perl => JSON
316             ###
317              
318              
319             { # Convert
320              
321             sub PP_encode_json {
322 25146     25146 0 40688 my $self = shift;
323 25146         35405 my $obj = shift;
324              
325 25146         47549 $self->{indent_count} = 0;
326 25146         42351 $self->{depth} = 0;
327              
328 25146         38230 my $props = $self->{PROPS};
329              
330 25146 100   595   61433 $self->{keysort} = $self->{PROPS}[P_CANONICAL] ? sub { $a cmp $b } : undef;
  595         1293  
331              
332 25146 100       61151 if ($self->{sort_by}) {
333             $self->{keysort} = ref($self->{sort_by}) eq 'CODE' ? $self->{sort_by}
334             : $self->{sort_by} =~ /\D+/ ? $self->{sort_by}
335 3 100   22   24 : sub { $a cmp $b };
  22 100       30  
336             }
337              
338 25146 50 66     67572 encode_error("hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)")
339             if(!ref $obj and !$props->[ P_ALLOW_NONREF ]);
340              
341 25146         60982 my $str = $self->object_to_json($obj);
342              
343 25128 100       65595 $str .= "\n" if ( $self->{PROPS}[P_INDENT] ); # JSON::XS 2.26 compatible
344              
345 25128         85542 return $str;
346             }
347              
348              
349             sub object_to_json {
350 25502     25502 0 50455 my ($self, $obj) = @_;
351 25502         43988 my $type = ref($obj);
352              
353 25502 100       69438 if($type eq 'HASH'){
    100          
    100          
354 346         710 return $self->hash_to_json($obj);
355             }
356             elsif($type eq 'ARRAY'){
357 25015         59433 return $self->array_to_json($obj);
358             }
359             elsif ($type) { # blessed object?
360 57 100       212 if (blessed($obj)) {
361              
362 37 100       230 return $self->value_to_json($obj) if ( $obj->isa('JSON::PP::Boolean') );
363              
364 17 100 100     92 if ( $self->{PROPS}[P_ALLOW_TAGS] and $obj->can('FREEZE') ) {
365 1   33     4 my $obj_class = ref $obj || $obj;
366 1         2 $obj = bless $obj, $obj_class;
367 1         4 my @results = $obj->FREEZE('JSON');
368 1 50 33     1089 if ( @results and ref $results[0] ) {
369 0 0       0 if ( refaddr( $obj ) eq refaddr( $results[0] ) ) {
370 0         0 encode_error( sprintf(
371             "%s::FREEZE method returned same object as was passed instead of a new one",
372             ref $obj
373             ) );
374             }
375             }
376 1         10 return '("'.$obj_class.'")['.join(',', @results).']';
377             }
378              
379 16 100 100     142 if ( $self->{PROPS}[P_CONVERT_BLESSED] and $obj->can('TO_JSON') ) {
380 8         83 my $result = $obj->TO_JSON();
381 8 100 66     920 if ( defined $result and ref( $result ) ) {
382 2 100       16 if ( refaddr( $obj ) eq refaddr( $result ) ) {
383 1         8 encode_error( sprintf(
384             "%s::TO_JSON method returned same object as was passed instead of a new one",
385             ref $obj
386             ) );
387             }
388             }
389              
390 7         39 return $self->object_to_json( $result );
391             }
392              
393 8 100 66     30 return "$obj" if ( $self->{PROPS}[P_ALLOW_BIGNUM] and _is_bignum($obj) );
394              
395 5 100       11 if ($self->{PROPS}[P_ALLOW_BLESSED]) {
396 3 50       6 return $self->blessed_to_json($obj) if ($self->{PROPS}[P_AS_NONBLESSED]); # will be removed.
397 3         10 return 'null';
398             }
399 2         15 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)
400             );
401             }
402             else {
403 20         47 return $self->value_to_json($obj);
404             }
405             }
406             else{
407 84         183 return $self->value_to_json($obj);
408             }
409             }
410              
411              
412             sub hash_to_json {
413 346     346 0 519 my ($self, $obj) = @_;
414 346         488 my @res;
415              
416             encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)")
417 346 100       800 if (++$self->{depth} > $self->{max_depth});
418              
419 345 100       781 my ($pre, $post) = $self->{PROPS}[P_INDENT] ? $self->_up_indent() : ('', '');
420 345 100       990 my $del = ($self->{PROPS}[P_SPACE_BEFORE] ? ' ' : '') . ':' . ($self->{PROPS}[P_SPACE_AFTER] ? ' ' : '');
    100          
421              
422 345         649 for my $k ( $self->__sort( $obj ) ) {
423             push @res, $self->string_to_json( $k )
424             . $del
425 744 100       1539 . ( ref $obj->{$k} ? $self->object_to_json( $obj->{$k} ) : $self->value_to_json( $obj->{$k} ) );
426             }
427              
428 343         693 --$self->{depth};
429 343 100       702 $self->_down_indent() if ($self->{PROPS}[P_INDENT]);
430              
431 343 100       715 return '{}' unless @res;
432 333         1684 return '{' . $pre . join( ",$pre", @res ) . $post . '}';
433             }
434              
435              
436             sub array_to_json {
437 25015     25015 0 42743 my ($self, $obj) = @_;
438 25015         37562 my @res;
439              
440             encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)")
441 25015 100       61903 if (++$self->{depth} > $self->{max_depth});
442              
443 25014 100       65356 my ($pre, $post) = $self->{PROPS}[P_INDENT] ? $self->_up_indent() : ('', '');
444              
445 25014         52110 for my $v (@$obj){
446 25798 100       73532 push @res, ref($v) ? $self->object_to_json($v) : $self->value_to_json($v);
447             }
448              
449 25000         48530 --$self->{depth};
450 25000 100       54206 $self->_down_indent() if ($self->{PROPS}[P_INDENT]);
451              
452 25000 100       57756 return '[]' unless @res;
453 24987         196555 return '[' . $pre . join( ",$pre", @res ) . $post . ']';
454             }
455              
456             sub _looks_like_number {
457 26233     26233   39071 my $value = shift;
458 26233         34950 if (USE_B) {
459             my $b_obj = B::svref_2object(\$value);
460             my $flags = $b_obj->FLAGS;
461             return 1 if $flags & ( B::SVp_IOK() | B::SVp_NOK() ) and !( $flags & B::SVp_POK() );
462             return;
463             } else {
464 65     65   606 no warnings 'numeric';
  65         138  
  65         11111  
465             # if the utf8 flag is on, it almost certainly started as a string
466 26233 100       87491 return if utf8::is_utf8($value);
467             # detect numbers
468             # string & "" -> ""
469             # number & "" -> 0 (with warning)
470             # nan and inf can detect as numbers, so check with * 0
471 13746 100       61319 return unless length((my $dummy = "") & $value);
472 817 100       1961 return unless 0 + $value eq $value;
473 816 50       2288 return 1 if $value * 0 == 0;
474 0         0 return -1; # inf/nan
475             }
476             }
477              
478             sub value_to_json {
479 26317     26317 0 47106 my ($self, $value) = @_;
480              
481 26317 100       54654 return 'null' if(!defined $value);
482              
483 26273         42936 my $type = ref($value);
484              
485 26273 100 66     49061 if (!$type) {
    100          
486 65     65   76463 BEGIN { CORE_BOOL and warnings->unimport('experimental::builtin') }
487 26233 100       50633 if (CORE_BOOL && builtin::is_bool($value)) {
488             return $value ? 'true' : 'false';
489             }
490 0         0 elsif (_looks_like_number($value)) {
491 816         2225 return $value;
492             }
493 25417         65802 return $self->string_to_json($value);
494             }
495             elsif( blessed($value) and $value->isa('JSON::PP::Boolean') ){
496 20 100       134 return $$value == 1 ? 'true' : 'false';
497             }
498             else {
499 20 50       68 if ((overload::StrVal($value) =~ /=(\w+)/)[0]) {
500 0         0 return $self->value_to_json("$value");
501             }
502              
503 20 100 100     174 if ($type eq 'SCALAR' and defined $$value) {
504             return $$value eq '1' ? 'true'
505             : $$value eq '0' ? 'false'
506 7 100       51 : $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ? 'null'
    100          
    100          
507             : encode_error("cannot encode reference to scalar");
508             }
509              
510 13 100       33 if ( $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ) {
511 4         13 return 'null';
512             }
513             else {
514 9 100 100     40 if ( $type eq 'SCALAR' or $type eq 'REF' ) {
515 6         14 encode_error("cannot encode reference to scalar");
516             }
517             else {
518 3         14 encode_error("encountered $value, but JSON can only represent references to arrays or hashes");
519             }
520             }
521              
522             }
523             }
524              
525              
526             my %esc = (
527             "\n" => '\n',
528             "\r" => '\r',
529             "\t" => '\t',
530             "\f" => '\f',
531             "\b" => '\b',
532             "\"" => '\"',
533             "\\" => '\\\\',
534             "\'" => '\\\'',
535             );
536              
537              
538             sub string_to_json {
539 26161     26161 0 52615 my ($self, $arg) = @_;
540              
541 26161         491833 $arg =~ s/(["\\\n\r\t\f\b])/$esc{$1}/g;
542 26161 100       74465 $arg =~ s/\//\\\//g if ($self->{PROPS}[P_ESCAPE_SLASH]);
543              
544             # On ASCII platforms, matches [\x00-\x08\x0b\x0e-\x1f]
545 26161         175170 $arg =~ s/([^\n\t\c?[:^cntrl:][:^ascii:]])/'\\u00' . unpack('H2', $1)/eg;
  578676         1623473  
546              
547 26161 100       69765 if ($self->{PROPS}[P_ASCII]) {
548 12297         35039 $arg = _encode_ascii($arg);
549             }
550              
551 26161 100       198736 if ($self->{PROPS}[P_LATIN1]) {
552 2         6 $arg = _encode_latin1($arg);
553             }
554              
555 26161 100       55963 if ($self->{PROPS}[P_UTF8]) {
556 12551         57309 utf8::encode($arg);
557             }
558              
559 26161         245351 return '"' . $arg . '"';
560             }
561              
562              
563             sub blessed_to_json {
564 0   0 0 0 0 my $reftype = reftype($_[1]) || '';
565 0 0       0 if ($reftype eq 'HASH') {
    0          
566 0         0 return $_[0]->hash_to_json($_[1]);
567             }
568             elsif ($reftype eq 'ARRAY') {
569 0         0 return $_[0]->array_to_json($_[1]);
570             }
571             else {
572 0         0 return 'null';
573             }
574             }
575              
576              
577             sub encode_error {
578 18     18 0 37 my $error = shift;
579 18         2392 Carp::croak "$error";
580             }
581              
582              
583             sub __sort {
584 345     345   477 my $self = shift;
585 345         480 my $keysort = $self->{keysort};
586 345 100       771 defined $keysort ? (sort $keysort (keys %{$_[0]})) : keys %{$_[0]};
  222         1224  
  123         522  
587             }
588              
589              
590             sub _up_indent {
591 9     9   12 my $self = shift;
592 9         20 my $space = ' ' x $self->{indent_length};
593              
594 9         16 my ($pre,$post) = ('','');
595              
596 9         18 $post = "\n" . $space x $self->{indent_count};
597              
598 9         12 $self->{indent_count}++;
599              
600 9         16 $pre = "\n" . $space x $self->{indent_count};
601              
602 9         23 return ($pre,$post);
603             }
604              
605              
606 9     9   15 sub _down_indent { $_[0]->{indent_count}--; }
607              
608             } # Convert
609              
610              
611             sub _encode_ascii {
612             join('',
613             map {
614 12297 100   12297   342135 chr($_) =~ /[[:ascii:]]/ ?
  6259537 100       16393579  
615             chr($_) :
616             $_ <= 65535 ?
617             sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_));
618             } unpack('U*', $_[0])
619             );
620             }
621              
622              
623             sub _encode_latin1 {
624             join('',
625             map {
626 2 50   2   9 $_ <= 255 ?
  22 100       59  
627             chr($_) :
628             $_ <= 65535 ?
629             sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_));
630             } unpack('U*', $_[0])
631             );
632             }
633              
634              
635             sub _encode_surrogates { # from perlunicode
636 1127975     1127975   1449260 my $uni = $_[0] - 0x10000;
637 1127975         3226124 return ($uni / 0x400 + 0xD800, $uni % 0x400 + 0xDC00);
638             }
639              
640              
641             sub _is_bignum {
642 3 100   3   22 $_[0]->isa('Math::BigInt') or $_[0]->isa('Math::BigFloat');
643             }
644              
645              
646              
647             #
648             # JSON => Perl
649             #
650              
651             my $max_intsize;
652              
653             BEGIN {
654 65     65   307 my $checkint = 1111;
655 65         351 for my $d (5..64) {
656 1105         1937 $checkint .= 1;
657 1105         35077 my $int = eval qq| $checkint |;
658 1105 100       5426 if ($int =~ /[eE]/) {
659 65         153 $max_intsize = $d - 1;
660 65         21745 last;
661             }
662             }
663             }
664              
665             { # PARSE
666              
667             my %escapes = ( # by Jeremy Muhlich
668             b => "\b",
669             t => "\t",
670             n => "\n",
671             f => "\f",
672             r => "\r",
673             '\\' => '\\',
674             '"' => '"',
675             '/' => '/',
676             );
677              
678             sub _detect_utf_encoding {
679 12410     12410   20638 my $text = shift;
680 12410         41614 my @octets = unpack('C4', $text);
681 12410 100       31313 return 'unknown' unless defined $octets[3];
682 12390 0 100     57274 return ( $octets[0] and $octets[1]) ? 'UTF-8'
    50 66        
    50 33        
    100          
    100          
683             : (!$octets[0] and $octets[1]) ? 'UTF-16BE'
684             : (!$octets[0] and !$octets[1]) ? 'UTF-32BE'
685             : ( $octets[2] ) ? 'UTF-16LE'
686             : (!$octets[2] ) ? 'UTF-32LE'
687             : 'unknown';
688             }
689              
690             sub PP_decode_json {
691 25269     25269 0 66017 my ($self, $text, $want_offset) = @_;
692              
693 25269         73118 @$self{qw/at ch depth/} = (0, '', 0);
694              
695 25269 100 100     112296 if ( !defined $text or ref $text ) {
696 4         10 $self->_decode_error("malformed JSON string, neither array, object, number, string or atom");
697             }
698              
699 25265         44165 my $props = $self->{PROPS};
700              
701 25265 100       51837 if ( $self->{PROPS}[P_UTF8] ) {
702 12410         31636 my $encoding = _detect_utf_encoding($text);
703 12410 100 100     39759 if ($encoding ne 'UTF-8' and $encoding ne 'unknown') {
704 3         664 require Encode;
705 3         10287 Encode::from_to($text, $encoding, 'utf-8');
706             } else {
707 12407 100       39146 utf8::downgrade( $text, 1 ) or Carp::croak("Wide character in subroutine entry");
708             }
709             }
710             else {
711 12855         61967 utf8::encode( $text );
712             }
713              
714 25264         69426 $self->{len} = length $text;
715 25264         53825 $self->{text} = $text;
716              
717 25264 100       55254 if ($self->{max_size} > 1) {
718 65     65   41546 use bytes;
  65         973  
  65         338  
719 2         4 my $bytes = length $text;
720             $self->_decode_error(
721             sprintf("attempted decode of JSON text of %s bytes size, but max_size is set to %s"
722             , $bytes, $self->{max_size}), 1
723 2 100       12 ) if ($bytes > $self->{max_size});
724             }
725              
726 25263         66679 $self->_white(); # remove head white space
727              
728 25263 100       55540 $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?
729              
730 25261         54881 my $result = $self->_value();
731              
732 25184 100 100     91191 if ( !$props->[ P_ALLOW_NONREF ] and !ref $result ) {
733 5         18 $self->_decode_error(
734             'JSON text must be an object or array (but found number, string, true, false or null,'
735             . ' use allow_nonref to allow this)', 1);
736             }
737              
738 25179 50       62824 Carp::croak('something wrong.') if $self->{len} < $self->{at}; # we won't arrive here.
739              
740 25179 100       56245 my $consumed = defined $self->{ch} ? $self->{at} - 1 : $self->{at}; # consumed JSON text length
741              
742 25179         54629 $self->_white(); # remove tail white space
743              
744 25179 100       50241 return ( $result, $consumed ) if $want_offset; # all right if decode_prefix
745              
746 24875 100       50364 $self->_decode_error("garbage after JSON object") if defined $self->{ch};
747              
748 24863         201649 $result;
749             }
750              
751              
752             sub _next_chr {
753 36720055     36720055   44410502 my $self = shift;
754 36720055 100       61141414 return $self->{ch} = undef if($self->{at} >= $self->{len});
755 36694985         76692736 $self->{ch} = substr($self->{text}, $self->{at}++, 1);
756             }
757              
758              
759             sub _value {
760 53833     53833   73207 my $self = shift;
761 53833         100778 $self->_white();
762 53833         82569 my $ch = $self->{ch};
763 53833 50       96764 return if(!defined $ch);
764 53833 100       99426 return $self->_object() if($ch eq '{');
765 52443 100       115100 return $self->_array() if($ch eq '[');
766 26328 100       51881 return $self->_tag() if($ch eq '(');
767 26327 100 66     81593 return $self->_string() if($ch eq '"' or ($self->{PROPS}[P_ALLOW_SINGLEQUOTE] and $ch eq "'"));
      100        
768 905 100 100     3550 return $self->_number() if($ch =~ /[0-9]/ or $ch eq '-');
769 93         236 return $self->_word();
770             }
771              
772             sub _string {
773 27152     27152   39423 my $self = shift;
774 27152         41329 my $utf16;
775             my $is_utf8;
776              
777 27152         36937 my $utf8_len = 0;
778              
779 27152         36549 my $s = ''; # basically UTF8 flag on
780              
781 27152         41448 my $ch = $self->{ch};
782 27152 100 66     60501 if($ch eq '"' or ($self->{PROPS}[P_ALLOW_SINGLEQUOTE] and $ch eq "'")){
      100        
783 27147         36536 my $boundChar = $ch;
784              
785 27147         44291 OUTER: while( defined($ch = $self->_next_chr()) ){
786              
787 10715493 100       20986826 if($ch eq $boundChar){
    100          
788 27131         61930 $self->_next_chr();
789              
790 27131 100       54312 if ($utf16) {
791 1         3 $self->_decode_error("missing low surrogate character in surrogate pair");
792             }
793              
794 27130 100       135287 utf8::decode($s) if($is_utf8);
795              
796 27130         130654 return $s;
797             }
798             elsif($ch eq '\\'){
799 5300299         7569462 $ch = $self->_next_chr();
800 5300299 100       9915723 if(exists $escapes{$ch}){
    100          
801 152492         281195 $s .= $escapes{$ch};
802             }
803             elsif($ch eq 'u'){ # UNICODE handling
804 5147803         6337784 my $u = '';
805              
806 5147803         7743717 for(1..4){
807 20591212         29553764 $ch = $self->_next_chr();
808 20591212 50       49885267 last OUTER if($ch !~ /[0-9a-fA-F]/);
809 20591212         30561824 $u .= $ch;
810             }
811              
812             # U+D800 - U+DBFF
813 5147803 100       12081878 if ($u =~ /^[dD][89abAB][0-9a-fA-F]{2}/) { # UTF-16 high surrogate?
    100          
814 1127978         2138764 $utf16 = $u;
815             }
816             # U+DC00 - U+DFFF
817             elsif ($u =~ /^[dD][c-fC-F][0-9a-fA-F]{2}/) { # UTF-16 low surrogate?
818 1127977 100       1851422 unless (defined $utf16) {
819 1         3 $self->_decode_error("missing high surrogate character in surrogate pair");
820             }
821 1127976         1336146 $is_utf8 = 1;
822 1127976   50     1693743 $s .= _decode_surrogates($utf16, $u) || next;
823 1127976         2327385 $utf16 = undef;
824             }
825             else {
826 2891848 100       4614534 if (defined $utf16) {
827 1         3 $self->_decode_error("surrogate pair expected");
828             }
829              
830 2891847         4016686 my $hex = hex( $u );
831 2891847 50       4868686 if ( chr $u =~ /[[:^ascii:]]/ ) {
832 2891847         3329143 $is_utf8 = 1;
833 2891847   50     4196162 $s .= _decode_unicode($u) || next;
834             }
835             else {
836 0         0 $s .= chr $hex;
837             }
838             }
839              
840             }
841             else{
842 4 50       10 unless ($self->{PROPS}[P_LOOSE]) {
843 4         8 $self->{at} -= 2;
844 4         9 $self->_decode_error('illegal backslash escape sequence in string');
845             }
846 0         0 $s .= $ch;
847             }
848             }
849             else{
850              
851 5388063 100       11765563 if ( $ch =~ /[[:^ascii:]]/ ) {
852 3441000 100       5972928 unless( $ch = $self->_is_valid_utf8($ch, \$utf8_len) ) {
853 5         14 $self->{at} -= 1;
854 5         14 $self->_decode_error("malformed UTF-8 character in JSON string");
855             }
856             else {
857 3440995         5270187 $self->{at} += $utf8_len - 1;
858             }
859              
860 3440995         4608851 $is_utf8 = 1;
861             }
862              
863 5388058 50       9336675 if (!$self->{PROPS}[P_LOOSE]) {
864 5388058 100       15404561 if ($ch =~ $invalid_char_re) { # '/' ok
865 4 50 33     26 if (!$self->{PROPS}[P_RELAXED] or $ch ne "\t") {
866 4         8 $self->{at}--;
867 4         28 $self->_decode_error(sprintf "invalid character 0x%X"
868             . " encountered while parsing JSON string",
869             ord $ch);
870             }
871             }
872             }
873              
874 5388054         10055886 $s .= $ch;
875             }
876             }
877             }
878              
879 6         37 $self->_decode_error("unexpected end of string while parsing JSON string");
880             }
881              
882              
883             sub _white {
884 162105     162105   204580 my $self = shift;
885 162105         233865 my $ch = $self->{ch};
886 162105         298500 while( defined $ch ){
887 164722 100 100     661560 if($ch eq '' or $ch =~ /\A[ \t\r\n]\z/){
    50 66        
888 27669         51483 $ch = $self->_next_chr();
889             }
890             elsif($self->{PROPS}[P_RELAXED] and $ch eq '/'){
891 0         0 $ch = $self->_next_chr();
892 0 0 0     0 if(defined $ch and $ch eq '/'){
    0 0        
893 0   0     0 1 while(defined($ch = $self->_next_chr()) and $ch ne "\n" and $ch ne "\r");
      0        
894             }
895             elsif(defined $ch and $ch eq '*'){
896 0         0 $ch = $self->_next_chr();
897 0         0 while(1){
898 0 0       0 if(defined $ch){
899 0 0       0 if($ch eq '*'){
900 0 0 0     0 if(defined($ch = $self->_next_chr()) and $ch eq '/'){
901 0         0 $ch = $self->_next_chr();
902 0         0 last;
903             }
904             }
905             else{
906 0         0 $ch = $self->_next_chr();
907             }
908             }
909             else{
910 0         0 $self->_decode_error("Unterminated comment");
911             }
912             }
913 0         0 next;
914             }
915             else{
916 0         0 $self->{at}--;
917 0         0 $self->_decode_error("malformed JSON string, neither array, object, number, string or atom");
918             }
919             }
920             else{
921 137053 100 100     275978 if ($self->{PROPS}[P_RELAXED] and $ch eq '#') { # correctly?
922 9         40 pos($self->{text}) = $self->{at};
923 9         40 $self->{text} =~ /\G([^\n]*(?:\r\n|\r|\n|$))/g;
924 9         18 $self->{at} = pos($self->{text});
925 9         17 $ch = $self->_next_chr;
926 9         19 next;
927             }
928              
929 137044         202938 last;
930             }
931             }
932             }
933              
934              
935             sub _array {
936 26115     26115   36623 my $self = shift;
937 26115   50     80570 my $a = $_[0] || []; # you can use this code to use another array ref object.
938              
939             $self->_decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
940 26115 100       65223 if (++$self->{depth} > $self->{max_depth});
941              
942 26112         54980 $self->_next_chr();
943 26112         54885 $self->_white();
944              
945 26112         43085 my $ch = $self->{ch};
946 26112 100 66     86115 if(defined $ch and $ch eq ']'){
947 23         65 --$self->{depth};
948 23         67 $self->_next_chr();
949 23         55 return $a;
950             }
951             else {
952 26089         51970 while(defined($ch)){
953 26846         55571 push @$a, $self->_value();
954              
955 26279         73766 $self->_white();
956              
957 26279         46990 $ch = $self->{ch};
958 26279 100       56348 if (!defined $ch) {
959 3         11 last;
960             }
961              
962 26276 100       57102 if($ch eq ']'){
963 25514         40730 --$self->{depth};
964 25514         54695 $self->_next_chr();
965 25514         60214 return $a;
966             }
967              
968 762 100       1275 if($ch ne ','){
969 3         5 last;
970             }
971              
972 759         1485 $self->_next_chr();
973 759         1442 $self->_white();
974              
975 759         1052 $ch = $self->{ch};
976 759 100 100     1828 if ($self->{PROPS}[P_RELAXED] and $ch eq ']') {
977 2         4 --$self->{depth};
978 2         5 $self->_next_chr();
979 2         7 return $a;
980             }
981              
982             }
983             }
984              
985 6 100 66     32 $self->{at}-- if defined $ch and $ch ne '';
986 6         32 $self->_decode_error(", or ] expected while parsing array");
987             }
988              
989             sub _tag {
990 1     1   1 my $self = shift;
991 1 50       4 $self->_decode_error('malformed JSON string, neither array, object, number, string or atom') unless $self->{PROPS}[P_ALLOW_TAGS];
992              
993 1         4 $self->_next_chr();
994 1         3 $self->_white();
995              
996 1         4 my $tag = $self->_value();
997 1 50       6 return unless defined $tag;
998 1 50       2 $self->_decode_error('malformed JSON string, (tag) must be a string') if ref $tag;
999              
1000 1         4 $self->_white();
1001              
1002 1         2 my $ch = $self->{ch};
1003 1 50 33     6 if (!defined $ch or $ch ne ')') {
1004 0         0 $self->_decode_error(') expected after tag');
1005             }
1006              
1007 1         11 $self->_next_chr();
1008 1         3 $self->_white();
1009              
1010 1         8 my $val = $self->_value();
1011 1 50       4 return unless defined $val;
1012 1 50       4 $self->_decode_error('malformed JSON string, tag value must be an array') unless ref $val eq 'ARRAY';
1013              
1014 1 50       2 if (!eval { $tag->can('THAW') }) {
  1         14  
1015 0 0       0 $self->_decode_error('cannot decode perl-object (package does not exist)') if $@;
1016 0         0 $self->_decode_error('cannot decode perl-object (package does not have a THAW method)');
1017             }
1018 1         7 $tag->THAW('JSON', @$val);
1019             }
1020              
1021             sub _object {
1022 1390     1390   2083 my $self = shift;
1023 1390   50     3923 my $o = $_[0] || {}; # you can use this code to use another hash ref object.
1024 1390         1962 my $k;
1025              
1026             $self->_decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
1027 1390 50       2874 if (++$self->{depth} > $self->{max_depth});
1028 1390         2734 $self->_next_chr();
1029 1390         2873 $self->_white();
1030              
1031 1390         2367 my $ch = $self->{ch};
1032 1390 100 66     3886 if(defined $ch and $ch eq '}'){
1033 9         32 --$self->{depth};
1034 9         26 $self->_next_chr();
1035 9 100       38 if ($self->{F_HOOK}) {
1036 1         6 return $self->__json_object_hook($o);
1037             }
1038 8         29 return $o;
1039             }
1040             else {
1041 1381         2456 while (defined $ch) {
1042 1732 100 66     4909 $k = ($self->{PROPS}[P_ALLOW_BAREKEY] and $ch ne '"' and $ch ne "'") ? $self->_bareKey() : $self->_string();
1043 1727         3709 $self->_white();
1044              
1045 1727         2645 $ch = $self->{ch};
1046 1727 100 100     5005 if(!defined $ch or $ch ne ':'){
1047 3         6 $self->{at}--;
1048 3         8 $self->_decode_error("':' expected");
1049             }
1050              
1051 1724         3417 $self->_next_chr();
1052 1724         3309 $o->{$k} = $self->_value();
1053 1207         2749 $self->_white();
1054              
1055 1207         1850 $ch = $self->{ch};
1056 1207 100       2126 last if (!defined $ch);
1057              
1058 1205 100       2117 if($ch eq '}'){
1059 847         1207 --$self->{depth};
1060 847         1787 $self->_next_chr();
1061 847 100       1531 if ($self->{F_HOOK}) {
1062 8         18 return $self->__json_object_hook($o);
1063             }
1064 839         2725 return $o;
1065             }
1066              
1067 358 100       642 if($ch ne ','){
1068 5         9 last;
1069             }
1070              
1071 353         706 $self->_next_chr();
1072 353         687 $self->_white();
1073              
1074 353         580 $ch = $self->{ch};
1075 353 100 66     939 if ($self->{PROPS}[P_RELAXED] and $ch eq '}') {
1076 1         6 --$self->{depth};
1077 1         52 $self->_next_chr();
1078 1 50       37 if ($self->{F_HOOK}) {
1079 0         0 return $self->__json_object_hook($o);
1080             }
1081 1         6 return $o;
1082             }
1083              
1084             }
1085              
1086             }
1087              
1088 8 100 66     44 $self->{at}-- if defined $ch and $ch ne '';
1089 8         25 $self->_decode_error(", or } expected while parsing object/hash");
1090             }
1091              
1092              
1093             sub _bareKey { # doesn't strictly follow Standard ECMA-262 3rd Edition
1094 2     2   5 my $self = shift;
1095 2         4 my $key;
1096 2         5 my $ch = $self->{ch};
1097 2         12 while($ch =~ /[\$\w[:^ascii:]]/){
1098 6         14 $key .= $ch;
1099 6         10 $ch = $self->_next_chr();
1100             }
1101 2         7 return $key;
1102             }
1103              
1104              
1105             sub _word {
1106 93     93   142 my $self = shift;
1107 93         243 my $word = substr($self->{text},$self->{at}-1,4);
1108              
1109 93 100       317 if($word eq 'true'){
    100          
    100          
1110 14         28 $self->{at} += 3;
1111 14         33 $self->_next_chr;
1112 14 100       53 return defined $self->{true} ? $self->{true} : $JSON::PP::true;
1113             }
1114             elsif($word eq 'null'){
1115 44         75 $self->{at} += 3;
1116 44         108 $self->_next_chr;
1117 44         118 return undef;
1118             }
1119             elsif($word eq 'fals'){
1120 11         21 $self->{at} += 3;
1121 11 50       32 if(substr($self->{text},$self->{at},1) eq 'e'){
1122 11         19 $self->{at}++;
1123 11         24 $self->_next_chr;
1124 11 100       37 return defined $self->{false} ? $self->{false} : $JSON::PP::false;
1125             }
1126             }
1127              
1128 24         42 $self->{at}--; # for decode_error report
1129              
1130 24 100       64 $self->_decode_error("'null' expected") if ($word =~ /^n/);
1131 23 100       56 $self->_decode_error("'true' expected") if ($word =~ /^t/);
1132 22 50       46 $self->_decode_error("'false' expected") if ($word =~ /^f/);
1133 22         51 $self->_decode_error("malformed JSON string, neither array, object, number, string or atom");
1134             }
1135              
1136              
1137             sub _number {
1138 812     812   1271 my $self = shift;
1139 812         1131 my $n = '';
1140 812         1647 my $v;
1141             my $is_dec;
1142 812         0 my $is_exp;
1143              
1144 812         1246 my $ch = $self->{ch};
1145 812 100       1461 if($ch eq '-'){
1146 41         89 $n = '-';
1147 41         84 $ch = $self->_next_chr;
1148 41 100 66     248 if (!defined $ch or $ch !~ /\d/) {
1149 1         2 $self->_decode_error("malformed number (no digits after initial minus)");
1150             }
1151             }
1152              
1153             # According to RFC4627, hex or oct digits are invalid.
1154 811 100       1386 if($ch eq '0'){
1155 46         90 my $peek = substr($self->{text},$self->{at},1);
1156 46 100       124 if($peek =~ /^[0-9a-dfA-DF]/){ # e may be valid (exponential)
1157 5         16 $self->_decode_error("malformed number (leading zero must not be followed by another digit)");
1158             }
1159 41         67 $n .= $ch;
1160 41         80 $ch = $self->_next_chr;
1161             }
1162              
1163 806   100     3049 while(defined $ch and $ch =~ /\d/){
1164 971         1482 $n .= $ch;
1165 971         1514 $ch = $self->_next_chr;
1166             }
1167              
1168 806 100 100     2599 if(defined $ch and $ch eq '.'){
1169 49         94 $n .= '.';
1170 49         68 $is_dec = 1;
1171              
1172 49         117 $ch = $self->_next_chr;
1173 49 100 66     221 if (!defined $ch or $ch !~ /\d/) {
1174 1         4 $self->_decode_error("malformed number (no digits after decimal point)");
1175             }
1176             else {
1177 48         79 $n .= $ch;
1178             }
1179              
1180 48   100     91 while(defined($ch = $self->_next_chr) and $ch =~ /\d/){
1181 97         196 $n .= $ch;
1182             }
1183             }
1184              
1185 805 100 100     3013 if(defined $ch and ($ch eq 'e' or $ch eq 'E')){
      100        
1186 58         88 $n .= $ch;
1187 58         83 $is_exp = 1;
1188 58         117 $ch = $self->_next_chr;
1189              
1190 58 100 100     341 if(defined($ch) and ($ch eq '+' or $ch eq '-')){
    100 100        
      100        
1191 38         68 $n .= $ch;
1192 38         63 $ch = $self->_next_chr;
1193 38 100 66     171 if (!defined $ch or $ch =~ /\D/) {
1194 2         7 $self->_decode_error("malformed number (no digits after exp sign)");
1195             }
1196 36         111 $n .= $ch;
1197             }
1198             elsif(defined($ch) and $ch =~ /\d/){
1199 18         35 $n .= $ch;
1200             }
1201             else {
1202 2         6 $self->_decode_error("malformed number (no digits after exp sign)");
1203             }
1204              
1205 54   100     138 while(defined($ch = $self->_next_chr) and $ch =~ /\d/){
1206 33         65 $n .= $ch;
1207             }
1208              
1209             }
1210              
1211 801         1338 $v .= $n;
1212              
1213 801 100 100     2127 if ($is_dec or $is_exp) {
1214 70 100       174 if ($self->{PROPS}[P_ALLOW_BIGNUM]) {
1215 1         1230 require Math::BigFloat;
1216 1         28170 return Math::BigFloat->new($v);
1217             }
1218             } else {
1219 731 100       1350 if (length $v > $max_intsize) {
1220 1 50       3 if ($self->{PROPS}[P_ALLOW_BIGNUM]) { # from Adam Sussman
1221 1         8 require Math::BigInt;
1222 1         6 return Math::BigInt->new($v);
1223             }
1224             else {
1225 0         0 return "$v";
1226             }
1227             }
1228             }
1229              
1230 799 100       2792 return $is_dec ? $v/1.0 : 0+$v;
1231             }
1232              
1233             # Compute how many bytes are in the longest legal official Unicode
1234             # character
1235             my $max_unicode_length = do {
1236 65     65   197742 no warnings 'utf8';
  65         150  
  65         68395  
1237             chr 0x10FFFF;
1238             };
1239             utf8::encode($max_unicode_length);
1240             $max_unicode_length = length $max_unicode_length;
1241              
1242             sub _is_valid_utf8 {
1243 3441000     3441000   5623443 my ($self, $ch, $utf8_len_r) = @_;
1244              
1245             # Returns undef (setting $utf8_len to 0) unless the next bytes in $text
1246             # comprise a well-formed UTF-8 encoded character, in which case,
1247             # return those bytes, setting $utf8_len to their count.
1248              
1249 3441000         7343948 my $start_point = substr($self->{text}, $self->{at} - 1);
1250              
1251             # Look no further than the maximum number of bytes in a single
1252             # character
1253 3441000         4390472 my $limit = $max_unicode_length;
1254 3441000 100       5598989 $limit = length($start_point) if $limit > length($start_point);
1255              
1256             # Find the number of bytes comprising the first character in $text
1257             # (without having to know the details of its internal representation).
1258             # This loop will iterate just once on well-formed input.
1259 3441000         5560480 while ($limit > 0) { # Until we succeed or exhaust the input
1260 4681125         6364739 my $copy = substr($start_point, 0, $limit);
1261              
1262             # decode() will return true if all bytes are valid; false
1263             # if any aren't.
1264 4681125 100       9056544 if (utf8::decode($copy)) {
1265              
1266             # Is valid: get the first character, convert back to bytes,
1267             # and return those bytes.
1268 3440995         7456339 $copy = substr($copy, 0, 1);
1269 3440995         6625530 utf8::encode($copy);
1270 3440995         4290542 $$utf8_len_r = length $copy;
1271 3440995         8716608 return substr($start_point, 0, $$utf8_len_r);
1272             }
1273              
1274             # If it didn't work, it could be that there is a full legal character
1275             # followed by a partial or malformed one. Narrow the window and
1276             # try again.
1277 1240130         2080553 $limit--;
1278             }
1279              
1280             # Failed to find a legal UTF-8 character.
1281 5         10 $$utf8_len_r = 0;
1282 5         17 return;
1283             }
1284              
1285              
1286             sub _decode_error {
1287 101     101   223 my $self = shift;
1288 101         183 my $error = shift;
1289 101         180 my $no_rep = shift;
1290 101 100       334 my $str = defined $self->{text} ? substr($self->{text}, $self->{at}) : '';
1291 101         159 my $mess = '';
1292 101         154 my $type = 'U*';
1293              
1294 101         588 for my $c ( unpack( $type, $str ) ) { # emulate pv_uni_display() ?
1295 411         723 my $chr_c = chr($c);
1296 411 50       1280 $mess .= $chr_c eq '\\' ? '\\\\'
    50          
    50          
    50          
    50          
    100          
    100          
1297             : $chr_c =~ /[[:print:]]/ ? $chr_c
1298             : $chr_c eq '\a' ? '\a'
1299             : $chr_c eq '\t' ? '\t'
1300             : $chr_c eq '\n' ? '\n'
1301             : $chr_c eq '\r' ? '\r'
1302             : $chr_c eq '\f' ? '\f'
1303             : sprintf('\x{%x}', $c)
1304             ;
1305 411 100       840 if ( length $mess >= 20 ) {
1306 10         18 $mess .= '...';
1307 10         23 last;
1308             }
1309             }
1310              
1311 101 100       306 unless ( length $mess ) {
1312 33         69 $mess = '(end of string)';
1313             }
1314              
1315             Carp::croak (
1316 101 100       35118 $no_rep ? "$error" : "$error, at character offset $self->{at} (before \"$mess\")"
1317             );
1318              
1319             }
1320              
1321              
1322             sub __json_object_hook {
1323 9     9   12 my $self = shift;
1324 9         14 my $o = $_[0];
1325 9         14 my @ks = keys %{$o};
  9         32  
1326              
1327 9 100 66     80 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        
1328 4         13 my @val = $self->{cb_sk_object}{ $ks[0] }->( $o->{$ks[0]} );
1329 4 100       20 if (@val == 0) {
    50          
1330 1         4 return $o;
1331             }
1332             elsif (@val == 1) {
1333 3         14 return $val[0];
1334             }
1335             else {
1336 0         0 Carp::croak("filter_json_single_key_object callbacks must not return more than one scalar");
1337             }
1338             }
1339              
1340 5 100       20 my @val = $self->{cb_object}->($o) if ($self->{cb_object});
1341 5 100       20 if (@val == 0) {
    50          
1342 3         11 return $o;
1343             }
1344             elsif (@val == 1) {
1345 2         11 return $val[0];
1346             }
1347             else {
1348 0         0 Carp::croak("filter_json_object callbacks must not return more than one scalar");
1349             }
1350             }
1351              
1352             } # PARSE
1353              
1354              
1355             sub _decode_surrogates { # from perlunicode
1356 1127976     1127976   1987043 my $uni = 0x10000 + (hex($_[0]) - 0xD800) * 0x400 + (hex($_[1]) - 0xDC00);
1357 1127976         2330792 my $un = pack('U*', $uni);
1358 1127976         2174405 utf8::encode( $un );
1359 1127976         2381891 return $un;
1360             }
1361              
1362              
1363             sub _decode_unicode {
1364 2891847     2891847   5721300 my $un = pack('U', hex shift);
1365 2891847         5516451 utf8::encode( $un );
1366 2891847         8147831 return $un;
1367             }
1368              
1369             sub incr_parse {
1370 744     744 1 53763 local $Carp::CarpLevel = 1;
1371 744   66     2329 ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_parse( @_ );
1372             }
1373              
1374              
1375             sub incr_skip {
1376 2   33 2 1 1642 ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_skip;
1377             }
1378              
1379              
1380             sub incr_reset {
1381 0   0 0 1 0 ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_reset;
1382             }
1383              
1384             sub incr_text : lvalue {
1385 304   33 304 1 42244 $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new;
1386              
1387 304 50       652 if ( $_[0]->{_incr_parser}->{incr_pos} ) {
1388 0         0 Carp::croak("incr_text cannot be called when the incremental parser already started parsing");
1389             }
1390 304         1869 $_[0]->{_incr_parser}->{incr_text};
1391             }
1392              
1393              
1394             ###############################
1395             # Utilities
1396             #
1397              
1398             # shamelessly copied and modified from JSON::XS code.
1399              
1400             $JSON::PP::true = do { bless \(my $dummy = 1), "JSON::PP::Boolean" };
1401             $JSON::PP::false = do { bless \(my $dummy = 0), "JSON::PP::Boolean" };
1402              
1403             sub is_bool {
1404 5 100   5 1 1273 if (blessed $_[0]) {
1405             return (
1406 2   33     23 $_[0]->isa("JSON::PP::Boolean")
1407             or $_[0]->isa("Types::Serialiser::BooleanBase")
1408             or $_[0]->isa("JSON::XS::Boolean")
1409             );
1410             }
1411 0         0 elsif (CORE_BOOL) {
1412 65     65   10451 BEGIN { CORE_BOOL and warnings->unimport('experimental::builtin') }
1413             return builtin::is_bool($_[0]);
1414             }
1415 3         13 return !!0;
1416             }
1417              
1418 3     3 1 545 sub true { $JSON::PP::true }
1419 3     3 1 13 sub false { $JSON::PP::false }
1420 0     0 1 0 sub null { undef; }
1421              
1422             ###############################
1423              
1424             package JSON::PP::IncrParser;
1425              
1426 65     65   600 use strict;
  65         132  
  65         2322  
1427              
1428 65     65   442 use constant INCR_M_WS => 0; # initial whitespace skipping
  65         169  
  65         4222  
1429 65     65   538 use constant INCR_M_STR => 1; # inside string
  65         209  
  65         3687  
1430 65     65   422 use constant INCR_M_BS => 2; # inside backslash
  65         158  
  65         3848  
1431 65     65   429 use constant INCR_M_JSON => 3; # outside anything, count nesting
  65         160  
  65         3384  
1432 65     65   387 use constant INCR_M_C0 => 4;
  65         149  
  65         3514  
1433 65     65   1081 use constant INCR_M_C1 => 5;
  65         159  
  65         3144  
1434 65     65   404 use constant INCR_M_TFN => 6;
  65         169  
  65         3845  
1435 65     65   414 use constant INCR_M_NUM => 7;
  65         160  
  65         20901  
1436              
1437             our $VERSION = '1.01';
1438              
1439             sub new {
1440 57     57   119 my ( $class ) = @_;
1441              
1442 57         344 bless {
1443             incr_nest => 0,
1444             incr_text => undef,
1445             incr_pos => 0,
1446             incr_mode => 0,
1447             }, $class;
1448             }
1449              
1450              
1451             sub incr_parse {
1452 744     744   1452 my ( $self, $coder, $text ) = @_;
1453              
1454 744 100       1522 $self->{incr_text} = '' unless ( defined $self->{incr_text} );
1455              
1456 744 100       1746 if ( defined $text ) {
1457 402         950 $self->{incr_text} .= $text;
1458             }
1459              
1460 744 100       1984 if ( defined wantarray ) {
1461 383         826 my $max_size = $coder->get_max_size;
1462 383         634 my $p = $self->{incr_pos};
1463 383         555 my @ret;
1464             {
1465 383         495 do {
  383         482  
1466 394 100 100     1529 unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) {
1467 393         971 $self->_incr_parse( $coder );
1468              
1469 392 100 100     821 if ( $max_size and $self->{incr_pos} > $max_size ) {
1470 1         100 Carp::croak("attempted decode of JSON text of $self->{incr_pos} bytes size, but max_size is set to $max_size");
1471             }
1472 391 100 100     1219 unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) {
1473             # as an optimisation, do not accumulate white space in the incr buffer
1474 83 100 100     242 if ( $self->{incr_mode} == INCR_M_WS and $self->{incr_pos} ) {
1475 7         13 $self->{incr_pos} = 0;
1476 7         12 $self->{incr_text} = '';
1477             }
1478 83         155 last;
1479             }
1480             }
1481              
1482 309 100       7856 unless ( $coder->get_utf8 ) {
1483 301         946 utf8::decode( $self->{incr_text} );
1484             }
1485              
1486 309         735 my ($obj, $offset) = $coder->PP_decode_json( $self->{incr_text}, 0x00000001 );
1487 298         611 push @ret, $obj;
1488 65     65   503 use bytes;
  65         178  
  65         329  
1489 298   50     784 $self->{incr_text} = substr( $self->{incr_text}, $offset || 0 );
1490 298         436 $self->{incr_pos} = 0;
1491 298         462 $self->{incr_nest} = 0;
1492 298         468 $self->{incr_mode} = 0;
1493 298 100       676 last unless wantarray;
1494             } while ( wantarray );
1495             }
1496              
1497 370 100       653 if ( wantarray ) {
1498 7         44 return @ret;
1499             }
1500             else { # in scalar context
1501 363 100       1333 return defined $ret[0] ? $ret[0] : undef;
1502             }
1503             }
1504             }
1505              
1506              
1507             sub _incr_parse {
1508 393     393   634 my ($self, $coder) = @_;
1509 393         862 my $text = $self->{incr_text};
1510 393         585 my $len = length $text;
1511 393         524 my $p = $self->{incr_pos};
1512              
1513             INCR_PARSE:
1514 393         750 while ( $len > $p ) {
1515 3084         4517 my $s = substr( $text, $p, 1 );
1516 3084 50       4757 last INCR_PARSE unless defined $s;
1517 3084         3863 my $mode = $self->{incr_mode};
1518              
1519 3084 100 100     11540 if ( $mode == INCR_M_WS ) {
    50          
    100          
    100          
    100          
    100          
    50          
1520 335         609 while ( $len > $p ) {
1521 594         858 $s = substr( $text, $p, 1 );
1522 594 50       1008 last INCR_PARSE unless defined $s;
1523 594 100       1046 if ( ord($s) > ord " " ) {
1524 328 100       615 if ( $s eq '#' ) {
1525 6         8 $self->{incr_mode} = INCR_M_C0;
1526 6         15 redo INCR_PARSE;
1527             } else {
1528 322         433 $self->{incr_mode} = INCR_M_JSON;
1529 322         620 redo INCR_PARSE;
1530             }
1531             }
1532 266         431 $p++;
1533             }
1534             } elsif ( $mode == INCR_M_BS ) {
1535 0         0 $p++;
1536 0         0 $self->{incr_mode} = INCR_M_STR;
1537 0         0 redo INCR_PARSE;
1538             } elsif ( $mode == INCR_M_C0 or $mode == INCR_M_C1 ) {
1539 9         18 while ( $len > $p ) {
1540 45         62 $s = substr( $text, $p, 1 );
1541 45 50       83 last INCR_PARSE unless defined $s;
1542 45 100       103 if ( $s eq "\n" ) {
1543 9 100       30 $self->{incr_mode} = $self->{incr_mode} == INCR_M_C0 ? INCR_M_WS : INCR_M_JSON;
1544 9         14 last;
1545             }
1546 36         52 $p++;
1547             }
1548 9         17 next;
1549             } elsif ( $mode == INCR_M_TFN ) {
1550 36 50 66     89 last INCR_PARSE if $p >= $len && $self->{incr_nest};
1551 35         61 while ( $len > $p ) {
1552 140         232 $s = substr( $text, $p++, 1 );
1553 140 100 66     498 next if defined $s and $s =~ /[rueals]/;
1554 35         45 last;
1555             }
1556 35         53 $p--;
1557 35         47 $self->{incr_mode} = INCR_M_JSON;
1558              
1559 35 50       62 last INCR_PARSE unless $self->{incr_nest};
1560 35         49 redo INCR_PARSE;
1561             } elsif ( $mode == INCR_M_NUM ) {
1562 399 100 100     728 last INCR_PARSE if $p >= $len && $self->{incr_nest};
1563 396         674 while ( $len > $p ) {
1564 482         742 $s = substr( $text, $p++, 1 );
1565 482 100 66     1594 next if defined $s and $s =~ /[0-9eE.+\-]/;
1566 389         503 last;
1567             }
1568 396         499 $p--;
1569 396         598 $self->{incr_mode} = INCR_M_JSON;
1570              
1571 396 100       689 last INCR_PARSE unless $self->{incr_nest};
1572 378         557 redo INCR_PARSE;
1573             } elsif ( $mode == INCR_M_STR ) {
1574 805         1462 while ( $len > $p ) {
1575 84413         104919 $s = substr( $text, $p, 1 );
1576 84413 50       127810 last INCR_PARSE unless defined $s;
1577 84413 100       147866 if ( $s eq '"' ) {
    100          
1578 780         954 $p++;
1579 780         1073 $self->{incr_mode} = INCR_M_JSON;
1580              
1581 780 100       1352 last INCR_PARSE unless $self->{incr_nest};
1582 760         1087 redo INCR_PARSE;
1583             }
1584             elsif ( $s eq '\\' ) {
1585 508         606 $p++;
1586 508 50       831 if ( !defined substr($text, $p, 1) ) {
1587 0         0 $self->{incr_mode} = INCR_M_BS;
1588 0         0 last INCR_PARSE;
1589             }
1590             }
1591 83633         125661 $p++;
1592             }
1593             } elsif ( $mode == INCR_M_JSON ) {
1594 1500         2512 while ( $len > $p ) {
1595 3614         5329 $s = substr( $text, $p++, 1 );
1596 3614 50 66     20922 if ( $s eq "\x00" ) {
    100 100        
    100 100        
    100 100        
    100          
    100          
    100          
    100          
1597 0         0 $p--;
1598 0         0 last INCR_PARSE;
1599             } elsif ( $s =~ /^[\t\n\r ]$/) {
1600 724 50       1314 if ( !$self->{incr_nest} ) {
1601 0         0 $p--; # do not eat the whitespace, let the next round do it
1602 0         0 last INCR_PARSE;
1603             }
1604 724         1247 next;
1605             } elsif ( $s eq 't' or $s eq 'f' or $s eq 'n' ) {
1606 36         55 $self->{incr_mode} = INCR_M_TFN;
1607 36         53 redo INCR_PARSE;
1608             } elsif ( $s =~ /^[0-9\-]$/ ) {
1609 398         603 $self->{incr_mode} = INCR_M_NUM;
1610 398         615 redo INCR_PARSE;
1611             } elsif ( $s eq '"' ) {
1612 783         1111 $self->{incr_mode} = INCR_M_STR;
1613 783         1093 redo INCR_PARSE;
1614             } elsif ( $s eq '[' or $s eq '{' ) {
1615 383 100       872 if ( ++$self->{incr_nest} > $coder->get_max_depth ) {
1616 1         98 Carp::croak('json text or perl structure exceeds maximum nesting level (max_depth set too low?)');
1617             }
1618 382         760 next;
1619             } elsif ( $s eq ']' or $s eq '}' ) {
1620 369 100       808 if ( --$self->{incr_nest} <= 0 ) {
1621 270         441 last INCR_PARSE;
1622             }
1623             } elsif ( $s eq '#' ) {
1624 3         7 $self->{incr_mode} = INCR_M_C1;
1625 3         4 redo INCR_PARSE;
1626             }
1627             }
1628             }
1629             }
1630              
1631 392         564 $self->{incr_pos} = $p;
1632 392 100       920 $self->{incr_parsing} = $p ? 1 : 0; # for backward compatibility
1633             }
1634              
1635              
1636             sub incr_text {
1637 0 0   0   0 if ( $_[0]->{incr_pos} ) {
1638 0         0 Carp::croak("incr_text cannot be called when the incremental parser already started parsing");
1639             }
1640 0         0 $_[0]->{incr_text};
1641             }
1642              
1643              
1644             sub incr_skip {
1645 2     2   6 my $self = shift;
1646 2         6 $self->{incr_text} = substr( $self->{incr_text}, $self->{incr_pos} );
1647 2         3 $self->{incr_pos} = 0;
1648 2         5 $self->{incr_mode} = 0;
1649 2         4 $self->{incr_nest} = 0;
1650             }
1651              
1652              
1653             sub incr_reset {
1654 0     0     my $self = shift;
1655 0           $self->{incr_text} = undef;
1656 0           $self->{incr_pos} = 0;
1657 0           $self->{incr_mode} = 0;
1658 0           $self->{incr_nest} = 0;
1659             }
1660              
1661             ###############################
1662              
1663              
1664             1;
1665             __END__