File Coverage

blib/lib/JSON/backportPP.pm
Criterion Covered Total %
statement 857 992 86.3
branch 511 646 79.1
condition 182 266 68.4
subroutine 140 168 83.3
pod 45 96 46.8
total 1735 2168 80.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   1210 use 5.005;
  57         149  
7 57     57   263 use strict;
  57         83  
  57         871  
8              
9 57     57   197 use Exporter ();
  57         72  
  57         1270  
10 57     57   1832 BEGIN { @JSON::backportPP::ISA = ('Exporter') }
11              
12 57     57   53075 use overload ();
  57         44371  
  57         1136  
13 57     57   17934 use JSON::backportPP::Boolean;
  57         111  
  57         1629  
14              
15 57     57   288 use Carp ();
  57         88  
  57         1864  
16             #use Devel::Peek;
17              
18             $JSON::backportPP::VERSION = '4.12';
19              
20             @JSON::PP::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 57     57   251 use constant P_ASCII => 0;
  57         77  
  57         5139  
26 57     57   299 use constant P_LATIN1 => 1;
  57         91  
  57         2751  
27 57     57   290 use constant P_UTF8 => 2;
  57         102  
  57         2279  
28 57     57   263 use constant P_INDENT => 3;
  57         121  
  57         2137  
29 57     57   272 use constant P_CANONICAL => 4;
  57         95  
  57         2399  
30 57     57   271 use constant P_SPACE_BEFORE => 5;
  57         71  
  57         2297  
31 57     57   291 use constant P_SPACE_AFTER => 6;
  57         97  
  57         2190  
32 57     57   248 use constant P_ALLOW_NONREF => 7;
  57         113  
  57         2256  
33 57     57   264 use constant P_SHRINK => 8;
  57         89  
  57         2009  
34 57     57   242 use constant P_ALLOW_BLESSED => 9;
  57         78  
  57         2551  
35 57     57   282 use constant P_CONVERT_BLESSED => 10;
  57         1219  
  57         3415  
36 57     57   252 use constant P_RELAXED => 11;
  57         75  
  57         2202  
37              
38 57     57   261 use constant P_LOOSE => 12;
  57         87  
  57         2221  
39 57     57   255 use constant P_ALLOW_BIGNUM => 13;
  57         72  
  57         1983  
40 57     57   312 use constant P_ALLOW_BAREKEY => 14;
  57         95  
  57         2164  
41 57     57   328 use constant P_ALLOW_SINGLEQUOTE => 15;
  57         79  
  57         2126  
42 57     57   261 use constant P_ESCAPE_SLASH => 16;
  57         99  
  57         1925  
43 57     57   242 use constant P_AS_NONBLESSED => 17;
  57         91  
  57         2037  
44              
45 57     57   279 use constant P_ALLOW_UNKNOWN => 18;
  57         95  
  57         2062  
46 57     57   255 use constant P_ALLOW_TAGS => 19;
  57         97  
  57         2837  
47              
48 57 50   57   319 use constant OLD_PERL => $] < 5.008 ? 1 : 0;
  57         109  
  57         2785  
49 57   50 57   271 use constant USE_B => $ENV{PERL_JSON_PP_USE_B} || 0;
  57         1173  
  57         2847  
50 57     57   274 use constant CORE_BOOL => defined &builtin::is_bool;
  57         109  
  57         5628  
51              
52             my $invalid_char_re;
53              
54             BEGIN {
55 57     57   173 $invalid_char_re = "[";
56 57         117 for my $i (0 .. 0x01F, 0x22, 0x5c) { # '/' is ok
57 1938         2181 $invalid_char_re .= quotemeta chr utf8::unicode_to_native($i);
58             }
59              
60 57         2623 $invalid_char_re = qr/$invalid_char_re]/;
61             }
62              
63             BEGIN {
64 57     57   6926 if (USE_B) {
65             require B;
66             }
67             }
68              
69             BEGIN {
70 57     57   305 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         118 my @pp_bit_properties = qw(
76             allow_singlequote allow_bignum loose
77             allow_barekey escape_slash as_nonblessed
78             );
79              
80             # Perl version check, Unicode handling is enabled?
81             # Helper module sets @JSON::PP::_properties.
82 57         66 if ( OLD_PERL ) {
83             my $helper = $] >= 5.006 ? 'JSON::backportPP::Compat5006' : 'JSON::backportPP::Compat5005';
84             eval qq| require $helper |;
85             if ($@) { Carp::croak $@; }
86             }
87              
88 57         126 for my $name (@xs_compati_bit_properties, @pp_bit_properties) {
89 1140         3568 my $property_id = 'P_' . uc($name);
90              
91 1140 50   2 1 128922 eval qq/
  2 50   1 1 853  
  2 50   10 1 5  
  2 50   24704 1 6  
  0 100   1 1 0  
  2 100   2 0 5  
  1 100   3 1 3  
  1 100   0 0 3  
  1 50   12298 1 2  
  0 50   16 1 0  
  1 50   13 1 2  
  10 50   1 1 663  
  10 100   0 0 21  
  7 100   0 0 18  
  3 0   7 0 7  
  10 0   7 0 42  
  24704 100   0 0 84314  
  24704 100   0 0 49180  
  9335 100   0 0 17471  
  15369 100   0 0 26130  
  24704 100   7 0 311474  
  1 100   7 0 811  
  1 50   7 0 2  
  1 50   0 0 3  
  0 0   7 0 0  
  1 0   7 0 2  
  2 100   0 0 26  
  2 100   7 0 4  
  2 0   7 0 6  
  0 0   7 0 0  
  2 0   7 0 17  
  3 0   316 0 576  
  3 100   12 1 6  
  2 100   8 1 5  
  1 100   0 1 2  
  3 0   20 1 4  
  0 100   21510 1 0  
  0 100   13 1 0  
  0 0   12 1 0  
  0 100   18457 1 0  
  0 100       0  
  12298 100       30947  
  12298 100       20348  
  12296 100       22581  
  2 100       3  
  12298 100       68548  
  16 100       520  
  16 100       29  
  14 0       26  
  2 0       4  
  16 100       36  
  13 100       445  
  13 100       25  
  10 100       24  
  3 100       5  
  13 100       51  
  1 100       4  
  1 100       3  
  1 100       3  
  0 100       0  
  1         3  
  0         0  
  0         0  
  7         243  
  7         267  
  0         0  
  0         0  
  0         0  
  0         0  
  7         630  
  7         243  
  7         244  
  0         0  
  7         240  
  7         249  
  0         0  
  7         229  
  7         241  
  7         261  
  7         281  
  316         1292  
  12         860  
  12         22  
  8         14  
  4         52  
  12         121  
  8         1134  
  8         18  
  6         13  
  2         3  
  8         54  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  20         497  
  20         36  
  18         41  
  2         4  
  20         29  
  21510         50224  
  21510         40961  
  21508         47642  
  2         3  
  21510         62417  
  13         412  
  13         18  
  8         15  
  5         10  
  13         16  
  12         434  
  12         21  
  8         12  
  4         6  
  12         88  
  18457         46007  
  18457         31569  
  18455         31126  
  2         4  
  18457         212119  
92             sub $name {
93             my \$enable = defined \$_[1] ? \$_[1] : 1;
94              
95             if (\$enable) {
96             \$_[0]->{PROPS}->[$property_id] = 1;
97             }
98             else {
99             \$_[0]->{PROPS}->[$property_id] = 0;
100             }
101              
102             \$_[0];
103             }
104              
105             sub get_$name {
106             \$_[0]->{PROPS}->[$property_id] ? 1 : '';
107             }
108             /;
109             }
110              
111             }
112              
113              
114              
115             # Functions
116              
117             my $JSON; # cache
118              
119             sub encode_json ($) { # encode
120 186   66 186 1 933 ($JSON ||= __PACKAGE__->new->utf8)->encode(@_);
121             }
122              
123              
124             sub decode_json { # decode
125 6206   66 6206 1 65077 ($JSON ||= __PACKAGE__->new->utf8)->decode(@_);
126             }
127              
128             # Obsoleted
129              
130             sub to_json($) {
131 0     0 0 0 Carp::croak ("JSON::PP::to_json has been renamed to encode_json.");
132             }
133              
134              
135             sub from_json($) {
136 0     0 0 0 Carp::croak ("JSON::PP::from_json has been renamed to decode_json.");
137             }
138              
139              
140             # Methods
141              
142             sub new {
143 43174     43174 1 2413711 my $class = shift;
144 43174         114429 my $self = {
145             max_depth => 512,
146             max_size => 0,
147             indent_length => 3,
148             };
149              
150 43174         95938 $self->{PROPS}[P_ALLOW_NONREF] = 1;
151              
152 43174         879775 bless $self, $class;
153             }
154              
155              
156             sub encode {
157 25163     25163 1 126900 return $_[0]->PP_encode_json($_[1]);
158             }
159              
160              
161             sub decode {
162 24967     24967 1 107085 return $_[0]->PP_decode_json($_[1], 0x00000000);
163             }
164              
165              
166             sub decode_prefix {
167 8     8 1 709 return $_[0]->PP_decode_json($_[1], 0x00000001);
168             }
169              
170              
171             # accessor
172              
173              
174             # pretty printing
175              
176             sub pretty {
177 5     5 1 2021 my ($self, $v) = @_;
178 5 50       22 my $enable = defined $v ? $v : 1;
179              
180 5 100       12 if ($enable) { # indent_length(3) for JSON::XS compatibility
181 3         61 $self->indent(1)->space_before(1)->space_after(1);
182             }
183             else {
184 2         42 $self->indent(0)->space_before(0)->space_after(0);
185             }
186              
187 5         10 $self;
188             }
189              
190             # etc
191              
192             sub max_depth {
193 7 100   7 1 1144 my $max = defined $_[1] ? $_[1] : 0x80000000;
194 7         11 $_[0]->{max_depth} = $max;
195 7         36 $_[0];
196             }
197              
198              
199 386     386 0 784 sub get_max_depth { $_[0]->{max_depth}; }
200              
201              
202             sub max_size {
203 5 100   5 1 383 my $max = defined $_[1] ? $_[1] : 0;
204 5         9 $_[0]->{max_size} = $max;
205 5         47 $_[0];
206             }
207              
208              
209 386     386 0 508 sub get_max_size { $_[0]->{max_size}; }
210              
211             sub boolean_values {
212 10     10 0 3322 my $self = shift;
213 10 100       16 if (@_) {
214 5         6 my ($false, $true) = @_;
215 5         9 $self->{false} = $false;
216 5         7 $self->{true} = $true;
217 5         5 if (CORE_BOOL) {
218 57     57   81334 BEGIN { CORE_BOOL and warnings->unimport(qw(experimental::builtin)) }
219             if (builtin::is_bool($true) && builtin::is_bool($false) && $true && !$false) {
220             $self->{core_bools} = !!1;
221             }
222             else {
223             delete $self->{core_bools};
224             }
225             }
226             } else {
227 5         7 delete $self->{false};
228 5         7 delete $self->{true};
229 5         4 delete $self->{core_bools};
230             }
231 10         14 return $self;
232             }
233              
234             sub core_bools {
235 0     0 0 0 my $self = shift;
236 0 0       0 my $core_bools = defined $_[0] ? $_[0] : 1;
237 0 0       0 if ($core_bools) {
238 0         0 $self->{true} = !!1;
239 0         0 $self->{false} = !!0;
240 0         0 $self->{core_bools} = !!1;
241             }
242             else {
243 0         0 $self->{true} = $JSON::PP::true;
244 0         0 $self->{false} = $JSON::PP::false;
245 0         0 $self->{core_bools} = !!0;
246             }
247 0         0 return $self;
248             }
249              
250             sub get_core_bools {
251 0     0 0 0 my $self = shift;
252 0         0 return !!$self->{core_bools};
253             }
254              
255             sub unblessed_bool {
256 0     0 0 0 my $self = shift;
257 0         0 return $self->core_bools(@_);
258             }
259              
260             sub get_unblessed_bool {
261 0     0 0 0 my $self = shift;
262 0         0 return $self->get_core_bools(@_);
263             }
264              
265             sub get_boolean_values {
266 10     10 0 4759 my $self = shift;
267 10 50 66     32 if (exists $self->{true} and exists $self->{false}) {
268 5         14 return @$self{qw/false true/};
269             }
270 5         11 return;
271             }
272              
273             sub filter_json_object {
274 3 100 66 3 1 11 if (defined $_[1] and ref $_[1] eq 'CODE') {
275 2         5 $_[0]->{cb_object} = $_[1];
276             } else {
277 1         2 delete $_[0]->{cb_object};
278             }
279 3 50 66     8 $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0;
280 3         4 $_[0];
281             }
282              
283             sub filter_json_single_key_object {
284 4 50 33 4 1 14 if (@_ == 1 or @_ > 3) {
285 0         0 Carp::croak("Usage: JSON::PP::filter_json_single_key_object(self, key, callback = undef)");
286             }
287 4 100 66     12 if (defined $_[2] and ref $_[2] eq 'CODE') {
288 3         15 $_[0]->{cb_sk_object}->{$_[1]} = $_[2];
289             } else {
290 1         4 delete $_[0]->{cb_sk_object}->{$_[1]};
291 1 50       1 delete $_[0]->{cb_sk_object} unless %{$_[0]->{cb_sk_object} || {}};
  1 50       18  
292             }
293 4 50 33     11 $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0;
294 4         5 $_[0];
295             }
296              
297             sub indent_length {
298 0 0 0 0 1 0 if (!defined $_[1] or $_[1] > 15 or $_[1] < 0) {
      0        
299 0         0 Carp::carp "The acceptable range of indent_length() is 0 to 15.";
300             }
301             else {
302 0         0 $_[0]->{indent_length} = $_[1];
303             }
304 0         0 $_[0];
305             }
306              
307             sub get_indent_length {
308 0     0 0 0 $_[0]->{indent_length};
309             }
310              
311             sub sort_by {
312 3 50   3 1 959 $_[0]->{sort_by} = defined $_[1] ? $_[1] : 1;
313 3         8 $_[0];
314             }
315              
316             sub allow_bigint {
317 0     0 0 0 Carp::carp("allow_bigint() is obsoleted. use allow_bignum() instead.");
318 0         0 $_[0]->allow_bignum;
319             }
320              
321             ###############################
322              
323             ###
324             ### Perl => JSON
325             ###
326              
327              
328             { # Convert
329              
330             my $max_depth;
331             my $indent;
332             my $ascii;
333             my $latin1;
334             my $utf8;
335             my $space_before;
336             my $space_after;
337             my $canonical;
338             my $allow_blessed;
339             my $convert_blessed;
340              
341             my $indent_length;
342             my $escape_slash;
343             my $bignum;
344             my $as_nonblessed;
345             my $allow_tags;
346              
347             my $depth;
348             my $indent_count;
349             my $keysort;
350              
351              
352             sub PP_encode_json {
353 25163     25163 0 30660 my $self = shift;
354 25163         35984 my $obj = shift;
355              
356 25163         31686 $indent_count = 0;
357 25163         28242 $depth = 0;
358              
359 25163         38345 my $props = $self->{PROPS};
360              
361             ($ascii, $latin1, $utf8, $indent, $canonical, $space_before, $space_after, $allow_blessed,
362             $convert_blessed, $escape_slash, $bignum, $as_nonblessed, $allow_tags)
363 25163         37208 = @{$props}[P_ASCII .. P_SPACE_AFTER, P_ALLOW_BLESSED, P_CONVERT_BLESSED,
  25163         74971  
364             P_ESCAPE_SLASH, P_ALLOW_BIGNUM, P_AS_NONBLESSED, P_ALLOW_TAGS];
365              
366 25163         30936 ($max_depth, $indent_length) = @{$self}{qw/max_depth indent_length/};
  25163         41244  
367              
368 25163 100   589   46250 $keysort = $canonical ? sub { $a cmp $b } : undef;
  589         954  
369              
370 25163 100       48021 if ($self->{sort_by}) {
371             $keysort = ref($self->{sort_by}) eq 'CODE' ? $self->{sort_by}
372             : $self->{sort_by} =~ /\D+/ ? $self->{sort_by}
373 3 100   18   14 : sub { $a cmp $b };
  18 100       55  
374             }
375              
376 25163 50 66     52058 encode_error("hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)")
377             if(!ref $obj and !$props->[ P_ALLOW_NONREF ]);
378              
379 25163         47735 my $str = $self->object_to_json($obj);
380              
381 25145 100       50067 $str .= "\n" if ( $indent ); # JSON::XS 2.26 compatible
382              
383 25145         67396 return $str;
384             }
385              
386              
387             sub object_to_json {
388 25523     25523 0 45595 my ($self, $obj) = @_;
389 25523         45076 my $type = ref($obj);
390              
391 25523 100       57671 if($type eq 'HASH'){
    100          
    100          
392 348         588 return $self->hash_to_json($obj);
393             }
394             elsif($type eq 'ARRAY'){
395 25021         52644 return $self->array_to_json($obj);
396             }
397             elsif ($type) { # blessed object?
398 67 100       187 if (blessed($obj)) {
399              
400 47 100       207 return $self->value_to_json($obj) if ( $obj->isa('JSON::PP::Boolean') );
401              
402 19 100 100     61 if ( $allow_tags and $obj->can('FREEZE') ) {
403 1   33     3 my $obj_class = ref $obj || $obj;
404 1         2 $obj = bless $obj, $obj_class;
405 1         3 my @results = $obj->FREEZE('JSON');
406 1 50 33     773 if ( @results and ref $results[0] ) {
407 0 0       0 if ( refaddr( $obj ) eq refaddr( $results[0] ) ) {
408 0         0 encode_error( sprintf(
409             "%s::FREEZE method returned same object as was passed instead of a new one",
410             ref $obj
411             ) );
412             }
413             }
414 1         6 return '("'.$obj_class.'")['.join(',', @results).']';
415             }
416              
417 18 100 100     84 if ( $convert_blessed and $obj->can('TO_JSON') ) {
418 9         47 my $result = $obj->TO_JSON();
419 9 100 66     651 if ( defined $result and ref( $result ) ) {
420 4 100       31 if ( refaddr( $obj ) eq refaddr( $result ) ) {
421 1         6 encode_error( sprintf(
422             "%s::TO_JSON method returned same object as was passed instead of a new one",
423             ref $obj
424             ) );
425             }
426             }
427              
428 8         39 return $self->object_to_json( $result );
429             }
430              
431 9 100 66     23 return "$obj" if ( $bignum and _is_bignum($obj) );
432              
433 6 100       10 if ($allow_blessed) {
434 4 50       7 return $self->blessed_to_json($obj) if ($as_nonblessed); # will be removed.
435 4         9 return 'null';
436             }
437 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)
438             );
439             }
440             else {
441 20         42 return $self->value_to_json($obj);
442             }
443             }
444             else{
445 87         168 return $self->value_to_json($obj);
446             }
447             }
448              
449              
450             sub hash_to_json {
451 348     348 0 408 my ($self, $obj) = @_;
452 348         386 my @res;
453              
454 348 100       566 encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)")
455             if (++$depth > $max_depth);
456              
457 347 100       619 my ($pre, $post) = $indent ? $self->_up_indent() : ('', '');
458 347 100       670 my $del = ($space_before ? ' ' : '') . ':' . ($space_after ? ' ' : '');
    100          
459              
460 347         496 for my $k ( _sort( $obj ) ) {
461 746         756 if ( OLD_PERL ) { utf8::decode($k) } # key for Perl 5.6 / be optimized
462             push @res, $self->string_to_json( $k )
463             . $del
464 746 100       1046 . ( ref $obj->{$k} ? $self->object_to_json( $obj->{$k} ) : $self->value_to_json( $obj->{$k} ) );
465             }
466              
467 345         452 --$depth;
468 345 100       529 $self->_down_indent() if ($indent);
469              
470 345 100       567 return '{}' unless @res;
471 335         1390 return '{' . $pre . join( ",$pre", @res ) . $post . '}';
472             }
473              
474              
475             sub array_to_json {
476 25021     25021 0 35238 my ($self, $obj) = @_;
477 25021         29158 my @res;
478              
479 25021 100       49557 encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)")
480             if (++$depth > $max_depth);
481              
482 25020 100       51393 my ($pre, $post) = $indent ? $self->_up_indent() : ('', '');
483              
484 25020         41508 for my $v (@$obj){
485 25812 100       67811 push @res, ref($v) ? $self->object_to_json($v) : $self->value_to_json($v);
486             }
487              
488 25006         33353 --$depth;
489 25006 100       34384 $self->_down_indent() if ($indent);
490              
491 25006 100       42877 return '[]' unless @res;
492 24996         159730 return '[' . $pre . join( ",$pre", @res ) . $post . ']';
493             }
494              
495             sub _looks_like_number {
496 26248     26248   30652 my $value = shift;
497 26248         25122 if (USE_B) {
498             my $b_obj = B::svref_2object(\$value);
499             my $flags = $b_obj->FLAGS;
500             return 1 if $flags & ( B::SVp_IOK() | B::SVp_NOK() ) and !( $flags & B::SVp_POK() );
501             return;
502             } else {
503 57     57   507 no warnings 'numeric';
  57         115  
  57         7423  
504             # if the utf8 flag is on, it almost certainly started as a string
505 26248 100       68527 return if utf8::is_utf8($value);
506             # detect numbers
507             # string & "" -> ""
508             # number & "" -> 0 (with warning)
509             # nan and inf can detect as numbers, so check with * 0
510 13761 100       52771 return unless length((my $dummy = "") & $value);
511 828 100       1403 return unless 0 + $value eq $value;
512 825 50       1804 return 1 if $value * 0 == 0;
513 0         0 return -1; # inf/nan
514             }
515             }
516              
517             sub value_to_json {
518 26341     26341 0 46291 my ($self, $value) = @_;
519              
520 26341 100       42761 return 'null' if(!defined $value);
521              
522 26296         33293 my $type = ref($value);
523              
524 26296 100 66     42945 if (!$type) {
    100          
525 57     57   49049 BEGIN { CORE_BOOL and warnings->unimport('experimental::builtin') }
526 26248 100       43285 if (CORE_BOOL && builtin::is_bool($value)) {
527             return $value ? 'true' : 'false';
528             }
529 0         0 elsif (_looks_like_number($value)) {
530 825         1647 return $value;
531             }
532 25423         66602 return $self->string_to_json($value);
533             }
534             elsif( blessed($value) and $value->isa('JSON::PP::Boolean') ){
535 28 100       154 return $$value == 1 ? 'true' : 'false';
536             }
537             else {
538 20 50       49 if ((overload::StrVal($value) =~ /=(\w+)/)[0]) {
539 0         0 return $self->value_to_json("$value");
540             }
541              
542 20 100 100     130 if ($type eq 'SCALAR' and defined $$value) {
543             return $$value eq '1' ? 'true'
544             : $$value eq '0' ? 'false'
545 7 100       36 : $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ? 'null'
    100          
    100          
546             : encode_error("cannot encode reference to scalar");
547             }
548              
549 13 100       22 if ( $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ) {
550 4         12 return 'null';
551             }
552             else {
553 9 100 100     31 if ( $type eq 'SCALAR' or $type eq 'REF' ) {
554 6         9 encode_error("cannot encode reference to scalar");
555             }
556             else {
557 3         11 encode_error("encountered $value, but JSON can only represent references to arrays or hashes");
558             }
559             }
560              
561             }
562             }
563              
564              
565             my %esc = (
566             "\n" => '\n',
567             "\r" => '\r',
568             "\t" => '\t',
569             "\f" => '\f',
570             "\b" => '\b',
571             "\"" => '\"',
572             "\\" => '\\\\',
573             "\'" => '\\\'',
574             );
575              
576              
577             sub string_to_json {
578 26169     26169 0 48263 my ($self, $arg) = @_;
579              
580 26169         388486 $arg =~ s/(["\\\n\r\t\f\b])/$esc{$1}/g;
581 26169 100       55382 $arg =~ s/\//\\\//g if ($escape_slash);
582              
583             # On ASCII platforms, matches [\x00-\x08\x0b\x0e-\x1f]
584 26169         129440 $arg =~ s/([^\n\t\c?[:^cntrl:][:^ascii:]])/'\\u00' . unpack('H2', $1)/eg;
  580660         1221425  
585              
586 26169 100       44545 if ($ascii) {
587 12297         26646 $arg = JSON_PP_encode_ascii($arg);
588             }
589              
590 26169 100       141542 if ($latin1) {
591 2         3 $arg = JSON_PP_encode_latin1($arg);
592             }
593              
594 26169 100       39145 if ($utf8) {
595 12551         43842 utf8::encode($arg);
596             }
597              
598 26169         188286 return '"' . $arg . '"';
599             }
600              
601              
602             sub blessed_to_json {
603 0   0 0 0 0 my $reftype = reftype($_[1]) || '';
604 0 0       0 if ($reftype eq 'HASH') {
    0          
605 0         0 return $_[0]->hash_to_json($_[1]);
606             }
607             elsif ($reftype eq 'ARRAY') {
608 0         0 return $_[0]->array_to_json($_[1]);
609             }
610             else {
611 0         0 return 'null';
612             }
613             }
614              
615              
616             sub encode_error {
617 18     18 0 23 my $error = shift;
618 18         1534 Carp::croak "$error";
619             }
620              
621              
622             sub _sort {
623 347 100   347   493 defined $keysort ? (sort $keysort (keys %{$_[0]})) : keys %{$_[0]};
  222         884  
  125         369  
624             }
625              
626              
627             sub _up_indent {
628 9     9   12 my $self = shift;
629 9         14 my $space = ' ' x $indent_length;
630              
631 9         13 my ($pre,$post) = ('','');
632              
633 9         15 $post = "\n" . $space x $indent_count;
634              
635 9         9 $indent_count++;
636              
637 9         14 $pre = "\n" . $space x $indent_count;
638              
639 9         19 return ($pre,$post);
640             }
641              
642              
643 9     9   11 sub _down_indent { $indent_count--; }
644              
645              
646             sub PP_encode_box {
647             {
648 0     0 1 0 depth => $depth,
649             indent_count => $indent_count,
650             };
651             }
652              
653             } # Convert
654              
655              
656             sub _encode_ascii {
657             join('',
658             map {
659 12297 100   12297   268683 chr($_) =~ /[[:ascii:]]/ ?
  6264941 100       11814803  
660             chr($_) :
661             $_ <= 65535 ?
662             sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_));
663             } unpack('U*', $_[0])
664             );
665             }
666              
667              
668             sub _encode_latin1 {
669             join('',
670             map {
671 2 50   2   7 $_ <= 255 ?
  22 100       39  
672             chr($_) :
673             $_ <= 65535 ?
674             sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_));
675             } unpack('U*', $_[0])
676             );
677             }
678              
679              
680             sub _encode_surrogates { # from perlunicode
681 1127735     1127735   1052716 my $uni = $_[0] - 0x10000;
682 1127735         2357641 return ($uni / 0x400 + 0xD800, $uni % 0x400 + 0xDC00);
683             }
684              
685              
686             sub _is_bignum {
687 3 100   3   15 $_[0]->isa('Math::BigInt') or $_[0]->isa('Math::BigFloat');
688             }
689              
690              
691              
692             #
693             # JSON => Perl
694             #
695              
696             my $max_intsize;
697              
698             BEGIN {
699 57     57   207 my $checkint = 1111;
700 57         219 for my $d (5..64) {
701 969         1308 $checkint .= 1;
702 969         23173 my $int = eval qq| $checkint |;
703 969 100       3440 if ($int =~ /[eE]/) {
704 57         108 $max_intsize = $d - 1;
705 57         19215 last;
706             }
707             }
708             }
709              
710             { # PARSE
711              
712             my %escapes = ( # by Jeremy Muhlich
713             b => "\b",
714             t => "\t",
715             n => "\n",
716             f => "\f",
717             r => "\r",
718             '\\' => '\\',
719             '"' => '"',
720             '/' => '/',
721             );
722              
723             my $text; # json data
724             my $at; # offset
725             my $ch; # first character
726             my $len; # text length (changed according to UTF8 or NON UTF8)
727             # INTERNAL
728             my $depth; # nest counter
729             my $encoding; # json text encoding
730             my $is_valid_utf8; # temp variable
731             my $utf8_len; # utf8 byte length
732             # FLAGS
733             my $utf8; # must be utf8
734             my $max_depth; # max nest number of objects and arrays
735             my $max_size;
736             my $relaxed;
737             my $cb_object;
738             my $cb_sk_object;
739              
740             my $F_HOOK;
741              
742             my $allow_bignum; # using Math::BigInt/BigFloat
743             my $singlequote; # loosely quoting
744             my $loose; #
745             my $allow_barekey; # bareKey
746             my $allow_tags;
747              
748             my $alt_true;
749             my $alt_false;
750              
751             sub _detect_utf_encoding {
752 12410     12410   19181 my $text = shift;
753 12410         32596 my @octets = unpack('C4', $text);
754 12410 100       24252 return 'unknown' unless defined $octets[3];
755 12390 0 100     43014 return ( $octets[0] and $octets[1]) ? 'UTF-8'
    50 66        
    50 33        
    100          
    100          
756             : (!$octets[0] and $octets[1]) ? 'UTF-16BE'
757             : (!$octets[0] and !$octets[1]) ? 'UTF-32BE'
758             : ( $octets[2] ) ? 'UTF-16LE'
759             : (!$octets[2] ) ? 'UTF-32LE'
760             : 'unknown';
761             }
762              
763             sub PP_decode_json {
764 25284     25284 0 32223 my ($self, $want_offset);
765              
766 25284         50696 ($self, $text, $want_offset) = @_;
767              
768 25284         42519 ($at, $ch, $depth) = (0, '', 0);
769              
770 25284 100 100     86444 if ( !defined $text or ref $text ) {
771 4         7 decode_error("malformed JSON string, neither array, object, number, string or atom");
772             }
773              
774 25280         37082 my $props = $self->{PROPS};
775              
776             ($utf8, $relaxed, $loose, $allow_bignum, $allow_barekey, $singlequote, $allow_tags)
777 25280         38406 = @{$props}[P_UTF8, P_RELAXED, P_LOOSE .. P_ALLOW_SINGLEQUOTE, P_ALLOW_TAGS];
  25280         52972  
778              
779 25280         49747 ($alt_true, $alt_false) = @$self{qw/true false/};
780              
781 25280 100       39927 if ( $utf8 ) {
782 12410         22435 $encoding = _detect_utf_encoding($text);
783 12410 100 100     29364 if ($encoding ne 'UTF-8' and $encoding ne 'unknown') {
784 3         437 require Encode;
785 3         7040 Encode::from_to($text, $encoding, 'utf-8');
786             } else {
787 12407 100       31882 utf8::downgrade( $text, 1 ) or Carp::croak("Wide character in subroutine entry");
788             }
789             }
790             else {
791 12870         46203 utf8::encode( $text );
792             }
793              
794 25279         36615 $len = length $text;
795              
796             ($max_depth, $max_size, $cb_object, $cb_sk_object, $F_HOOK)
797 25279         33187 = @{$self}{qw/max_depth max_size cb_object cb_sk_object F_HOOK/};
  25279         51359  
798              
799 25279 100       48075 if ($max_size > 1) {
800 57     57   29185 use bytes;
  57         650  
  57         237  
801 2         1 my $bytes = length $text;
802 2 100       16 decode_error(
803             sprintf("attempted decode of JSON text of %s bytes size, but max_size is set to %s"
804             , $bytes, $max_size), 1
805             ) if ($bytes > $max_size);
806             }
807              
808 25278         49118 white(); # remove head white space
809              
810 25278 100       42779 decode_error("malformed JSON string, neither array, object, number, string or atom") unless defined $ch; # Is there a first character for JSON structure?
811              
812 25276         36621 my $result = value();
813              
814 25199 100 100     97232 if ( !$props->[ P_ALLOW_NONREF ] and !ref $result ) {
815 5         16 decode_error(
816             'JSON text must be an object or array (but found number, string, true, false or null,'
817             . ' use allow_nonref to allow this)', 1);
818             }
819              
820 25194 50       45680 Carp::croak('something wrong.') if $len < $at; # we won't arrive here.
821              
822 25194 100       39579 my $consumed = defined $ch ? $at - 1 : $at; # consumed JSON text length
823              
824 25194         42839 white(); # remove tail white space
825              
826 25194 100       37611 return ( $result, $consumed ) if $want_offset; # all right if decode_prefix
827              
828 24890 100       33631 decode_error("garbage after JSON object") if defined $ch;
829              
830 24878         177345 $result;
831             }
832              
833              
834             sub next_chr {
835 36724965 100   36724965 0 40958108 return $ch = undef if($at >= $len);
836 36699880         47236079 $ch = substr($text, $at++, 1);
837             }
838              
839              
840             sub value {
841 53854     53854 0 71584 white();
842 53854 50       79349 return if(!defined $ch);
843 53854 100       71496 return object() if($ch eq '{');
844 52464 100       92713 return array() if($ch eq '[');
845 26345 100       44533 return tag() if($ch eq '(');
846 26344 100 66     55342 return string() if($ch eq '"' or ($singlequote and $ch eq "'"));
      100        
847 921 100 100     2427 return number() if($ch =~ /[0-9]/ or $ch eq '-');
848 109         193 return word();
849             }
850              
851             sub string {
852 27153     27153 1 31513 my $utf16;
853             my $is_utf8;
854              
855 27153         40186 ($is_valid_utf8, $utf8_len) = ('', 0);
856              
857 27153         31987 my $s = ''; # basically UTF8 flag on
858              
859 27153 100 66     42361 if($ch eq '"' or ($singlequote and $ch eq "'")){
      100        
860 27148         28038 my $boundChar = $ch;
861              
862 27148         29988 OUTER: while( defined(next_chr()) ){
863              
864 10715253 100       15087275 if($ch eq $boundChar){
    100          
865 27132         38157 next_chr();
866              
867 27132 100       39970 if ($utf16) {
868 1         2 decode_error("missing low surrogate character in surrogate pair");
869             }
870              
871 27131 100       103319 utf8::decode($s) if($is_utf8);
872              
873 27131         107062 return $s;
874             }
875             elsif($ch eq '\\'){
876 5302031         6474093 next_chr();
877 5302031 100       6842106 if(exists $escapes{$ch}){
    100          
878 153380         198906 $s .= $escapes{$ch};
879             }
880             elsif($ch eq 'u'){ # UNICODE handling
881 5148647         4563499 my $u = '';
882              
883 5148647         5562652 for(1..4){
884 20594588         19351412 $ch = next_chr();
885 20594588 50       34295873 last OUTER if($ch !~ /[0-9a-fA-F]/);
886 20594588         21935110 $u .= $ch;
887             }
888              
889             # U+D800 - U+DBFF
890 5148647 100       8349707 if ($u =~ /^[dD][89abAB][0-9a-fA-F]{2}/) { # UTF-16 high surrogate?
    100          
891 1127738         1370225 $utf16 = $u;
892             }
893             # U+DC00 - U+DFFF
894             elsif ($u =~ /^[dD][c-fC-F][0-9a-fA-F]{2}/) { # UTF-16 low surrogate?
895 1127737 100       1296992 unless (defined $utf16) {
896 1         3 decode_error("missing high surrogate character in surrogate pair");
897             }
898 1127736         959520 $is_utf8 = 1;
899 1127736   50     1206343 $s .= JSON_PP_decode_surrogates($utf16, $u) || next;
900 1127736         1550492 $utf16 = undef;
901             }
902             else {
903 2893172 100       3340757 if (defined $utf16) {
904 1         3 decode_error("surrogate pair expected");
905             }
906              
907 2893171         2866808 my $hex = hex( $u );
908 2893171 50       3597507 if ( chr $u =~ /[[:^ascii:]]/ ) {
909 2893171         2461159 $is_utf8 = 1;
910 2893171   50     2956456 $s .= JSON_PP_decode_unicode($u) || next;
911             }
912             else {
913 0         0 $s .= chr $hex;
914             }
915             }
916              
917             }
918             else{
919 4 50       19 unless ($loose) {
920 4         5 $at -= 2;
921 4         8 decode_error('illegal backslash escape sequence in string');
922             }
923 0         0 $s .= $ch;
924             }
925             }
926             else{
927              
928 5386090 100       8275669 if ( $ch =~ /[[:^ascii:]]/ ) {
929 3440100 100       3701583 unless( $ch = is_valid_utf8($ch) ) {
930 5         7 $at -= 1;
931 5         10 decode_error("malformed UTF-8 character in JSON string");
932             }
933             else {
934 3440095         3479457 $at += $utf8_len - 1;
935             }
936              
937 3440095         3205422 $is_utf8 = 1;
938             }
939              
940 5386085 50       6010366 if (!$loose) {
941 5386085 100       11156388 if ($ch =~ $invalid_char_re) { # '/' ok
942 4 50 33     12 if (!$relaxed or $ch ne "\t") {
943 4         4 $at--;
944 4         23 decode_error(sprintf "invalid character 0x%X"
945             . " encountered while parsing JSON string",
946             ord $ch);
947             }
948             }
949             }
950              
951 5386081         6363288 $s .= $ch;
952             }
953             }
954             }
955              
956 6         18 decode_error("unexpected end of string while parsing JSON string");
957             }
958              
959              
960             sub white {
961 162168     162168 0 221552 while( defined $ch ){
962 164785 100 100     474399 if($ch eq '' or $ch =~ /\A[ \t\r\n]\z/){
    50 66        
963 27684         34934 next_chr();
964             }
965             elsif($relaxed and $ch eq '/'){
966 0         0 next_chr();
967 0 0 0     0 if(defined $ch and $ch eq '/'){
    0 0        
968 0   0     0 1 while(defined(next_chr()) and $ch ne "\n" and $ch ne "\r");
      0        
969             }
970             elsif(defined $ch and $ch eq '*'){
971 0         0 next_chr();
972 0         0 while(1){
973 0 0       0 if(defined $ch){
974 0 0       0 if($ch eq '*'){
975 0 0 0     0 if(defined(next_chr()) and $ch eq '/'){
976 0         0 next_chr();
977 0         0 last;
978             }
979             }
980             else{
981 0         0 next_chr();
982             }
983             }
984             else{
985 0         0 decode_error("Unterminated comment");
986             }
987             }
988 0         0 next;
989             }
990             else{
991 0         0 $at--;
992 0         0 decode_error("malformed JSON string, neither array, object, number, string or atom");
993             }
994             }
995             else{
996 137101 100 100     191342 if ($relaxed and $ch eq '#') { # correctly?
997 9         21 pos($text) = $at;
998 9         32 $text =~ /\G([^\n]*(?:\r\n|\r|\n|$))/g;
999 9         11 $at = pos($text);
1000 9         17 next_chr;
1001 9         17 next;
1002             }
1003              
1004 137092         144494 last;
1005             }
1006             }
1007             }
1008              
1009              
1010             sub array {
1011 26119   50 26119 1 68747 my $a = $_[0] || []; # you can use this code to use another array ref object.
1012              
1013 26119 100       40960 decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
1014             if (++$depth > $max_depth);
1015              
1016 26116         42989 next_chr();
1017 26116         38856 white();
1018              
1019 26116 100 66     61792 if(defined $ch and $ch eq ']'){
1020 23         30 --$depth;
1021 23         40 next_chr();
1022 23         43 return $a;
1023             }
1024             else {
1025 26093         41513 while(defined($ch)){
1026 26852         42415 push @$a, value();
1027              
1028 26285         55303 white();
1029              
1030 26285 100       40770 if (!defined $ch) {
1031 3         5 last;
1032             }
1033              
1034 26282 100       45926 if($ch eq ']'){
1035 25518         27252 --$depth;
1036 25518         46297 next_chr();
1037 25518         55759 return $a;
1038             }
1039              
1040 764 100       974 if($ch ne ','){
1041 3         4 last;
1042             }
1043              
1044 761         1037 next_chr();
1045 761         1003 white();
1046              
1047 761 100 100     1290 if ($relaxed and $ch eq ']') {
1048 2         3 --$depth;
1049 2         12 next_chr();
1050 2         4 return $a;
1051             }
1052              
1053             }
1054             }
1055              
1056 6 100 66     24 $at-- if defined $ch and $ch ne '';
1057 6         13 decode_error(", or ] expected while parsing array");
1058             }
1059              
1060             sub tag {
1061 1 50   1 0 2 decode_error('malformed JSON string, neither array, object, number, string or atom') unless $allow_tags;
1062              
1063 1         2 next_chr();
1064 1         2 white();
1065              
1066 1         3 my $tag = value();
1067 1 50       3 return unless defined $tag;
1068 1 50       2 decode_error('malformed JSON string, (tag) must be a string') if ref $tag;
1069              
1070 1         2 white();
1071              
1072 1 50 33     5 if (!defined $ch or $ch ne ')') {
1073 0         0 decode_error(') expected after tag');
1074             }
1075              
1076 1         2 next_chr();
1077 1         7 white();
1078              
1079 1         2 my $val = value();
1080 1 50       2 return unless defined $val;
1081 1 50       3 decode_error('malformed JSON string, tag value must be an array') unless ref $val eq 'ARRAY';
1082              
1083 1 50       2 if (!eval { $tag->can('THAW') }) {
  1         5  
1084 0 0       0 decode_error('cannot decode perl-object (package does not exist)') if $@;
1085 0         0 decode_error('cannot decode perl-object (package does not have a THAW method)');
1086             }
1087 1         3 $tag->THAW('JSON', @$val);
1088             }
1089              
1090             sub object {
1091 1390   50 1390 1 3002 my $o = $_[0] || {}; # you can use this code to use another hash ref object.
1092 1390         1439 my $k;
1093              
1094 1390 50       1793 decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
1095             if (++$depth > $max_depth);
1096 1390         1900 next_chr();
1097 1390         1808 white();
1098              
1099 1390 100 66     2677 if(defined $ch and $ch eq '}'){
1100 9         13 --$depth;
1101 9         19 next_chr();
1102 9 100       27 if ($F_HOOK) {
1103 1         3 return _json_object_hook($o);
1104             }
1105 8         29 return $o;
1106             }
1107             else {
1108 1381         1782 while (defined $ch) {
1109 1732 100 66     2991 $k = ($allow_barekey and $ch ne '"' and $ch ne "'") ? bareKey() : string();
1110 1727         2739 white();
1111              
1112 1727 100 100     3588 if(!defined $ch or $ch ne ':'){
1113 3         5 $at--;
1114 3         7 decode_error("':' expected");
1115             }
1116              
1117 1724         2378 next_chr();
1118 1724         2103 $o->{$k} = value();
1119 1207         1811 white();
1120              
1121 1207 100       1511 last if (!defined $ch);
1122              
1123 1205 100       1532 if($ch eq '}'){
1124 847         796 --$depth;
1125 847         1153 next_chr();
1126 847 100       995 if ($F_HOOK) {
1127 8         11 return _json_object_hook($o);
1128             }
1129 839         1508 return $o;
1130             }
1131              
1132 358 100       510 if($ch ne ','){
1133 5         6 last;
1134             }
1135              
1136 353         514 next_chr();
1137 353         551 white();
1138              
1139 353 100 66     698 if ($relaxed and $ch eq '}') {
1140 1         1 --$depth;
1141 1         3 next_chr();
1142 1 50       13 if ($F_HOOK) {
1143 0         0 return _json_object_hook($o);
1144             }
1145 1         4 return $o;
1146             }
1147              
1148             }
1149              
1150             }
1151              
1152 8 100 66     32 $at-- if defined $ch and $ch ne '';
1153 8         27 decode_error(", or } expected while parsing object/hash");
1154             }
1155              
1156              
1157             sub bareKey { # doesn't strictly follow Standard ECMA-262 3rd Edition
1158 2     2 0 3 my $key;
1159 2         8 while($ch =~ /[\$\w[:^ascii:]]/){
1160 6         10 $key .= $ch;
1161 6         8 next_chr();
1162             }
1163 2         4 return $key;
1164             }
1165              
1166              
1167             sub word {
1168 109     109 0 285 my $word = substr($text,$at-1,4);
1169              
1170 109 100       257 if($word eq 'true'){
    100          
    100          
1171 21         28 $at += 3;
1172 21         34 next_chr;
1173 21 100       51 return defined $alt_true ? $alt_true : $JSON::PP::true;
1174             }
1175             elsif($word eq 'null'){
1176 46         49 $at += 3;
1177 46         69 next_chr;
1178 46         91 return undef;
1179             }
1180             elsif($word eq 'fals'){
1181 18         20 $at += 3;
1182 18 50       39 if(substr($text,$at,1) eq 'e'){
1183 18         22 $at++;
1184 18         28 next_chr;
1185 18 100       42 return defined $alt_false ? $alt_false : $JSON::PP::false;
1186             }
1187             }
1188              
1189 24         56 $at--; # for decode_error report
1190              
1191 24 100       96 decode_error("'null' expected") if ($word =~ /^n/);
1192 23 100       42 decode_error("'true' expected") if ($word =~ /^t/);
1193 22 50       135 decode_error("'false' expected") if ($word =~ /^f/);
1194 22         41 decode_error("malformed JSON string, neither array, object, number, string or atom");
1195             }
1196              
1197              
1198             sub number {
1199 812     812 1 982 my $n = '';
1200 812         1238 my $v;
1201             my $is_dec;
1202 812         0 my $is_exp;
1203              
1204 812 100       1215 if($ch eq '-'){
1205 41         53 $n = '-';
1206 41         67 next_chr;
1207 41 100 66     247 if (!defined $ch or $ch !~ /\d/) {
1208 1         3 decode_error("malformed number (no digits after initial minus)");
1209             }
1210             }
1211              
1212             # According to RFC4627, hex or oct digits are invalid.
1213 811 100       1025 if($ch eq '0'){
1214 46         1156 my $peek = substr($text,$at,1);
1215 46 100       86 if($peek =~ /^[0-9a-dfA-DF]/){ # e may be valid (exponential)
1216 5         16 decode_error("malformed number (leading zero must not be followed by another digit)");
1217             }
1218 41         50 $n .= $ch;
1219 41         50 next_chr;
1220             }
1221              
1222 806   100     2253 while(defined $ch and $ch =~ /\d/){
1223 971         1080 $n .= $ch;
1224 971         1089 next_chr;
1225             }
1226              
1227 806 100 100     1753 if(defined $ch and $ch eq '.'){
1228 49         53 $n .= '.';
1229 49         58 $is_dec = 1;
1230              
1231 49         78 next_chr;
1232 49 100 66     190 if (!defined $ch or $ch !~ /\d/) {
1233 1         2 decode_error("malformed number (no digits after decimal point)");
1234             }
1235             else {
1236 48         57 $n .= $ch;
1237             }
1238              
1239 48   100     63 while(defined(next_chr) and $ch =~ /\d/){
1240 97         134 $n .= $ch;
1241             }
1242             }
1243              
1244 805 100 100     2174 if(defined $ch and ($ch eq 'e' or $ch eq 'E')){
      100        
1245 58         77 $n .= $ch;
1246 58         72 $is_exp = 1;
1247 58         78 next_chr;
1248              
1249 58 100 100     223 if(defined($ch) and ($ch eq '+' or $ch eq '-')){
    100 100        
      100        
1250 38         85 $n .= $ch;
1251 38         63 next_chr;
1252 38 100 66     106 if (!defined $ch or $ch =~ /\D/) {
1253 2         3 decode_error("malformed number (no digits after exp sign)");
1254             }
1255 36         41 $n .= $ch;
1256             }
1257             elsif(defined($ch) and $ch =~ /\d/){
1258 18         22 $n .= $ch;
1259             }
1260             else {
1261 2         6 decode_error("malformed number (no digits after exp sign)");
1262             }
1263              
1264 54   100     65 while(defined(next_chr) and $ch =~ /\d/){
1265 33         42 $n .= $ch;
1266             }
1267              
1268             }
1269              
1270 801         872 $v .= $n;
1271              
1272 801 100 100     1582 if ($is_dec or $is_exp) {
1273 70 100       126 if ($allow_bignum) {
1274 1         29970 require Math::BigFloat;
1275 1         20131 return Math::BigFloat->new($v);
1276             }
1277             } else {
1278 731 100       1049 if (length $v > $max_intsize) {
1279 1 50       3 if ($allow_bignum) { # from Adam Sussman
1280 1         6 require Math::BigInt;
1281 1         3 return Math::BigInt->new($v);
1282             }
1283             else {
1284 0         0 return "$v";
1285             }
1286             }
1287             }
1288              
1289 799 100       1874 return $is_dec ? $v/1.0 : 0+$v;
1290             }
1291              
1292             # Compute how many bytes are in the longest legal official Unicode
1293             # character
1294             my $max_unicode_length = do {
1295 57 50 33 57   164996 BEGIN { $] >= 5.006 and require warnings and warnings->unimport('utf8') }
1296             chr 0x10FFFF;
1297             };
1298             utf8::encode($max_unicode_length);
1299             $max_unicode_length = length $max_unicode_length;
1300              
1301             sub is_valid_utf8 {
1302              
1303             # Returns undef (setting $utf8_len to 0) unless the next bytes in $text
1304             # comprise a well-formed UTF-8 encoded character, in which case,
1305             # return those bytes, setting $utf8_len to their count.
1306              
1307 3440100     3440100 0 4801588 my $start_point = substr($text, $at - 1);
1308              
1309             # Look no further than the maximum number of bytes in a single
1310             # character
1311 3440100         3159684 my $limit = $max_unicode_length;
1312 3440100 100       4100662 $limit = length($start_point) if $limit > length($start_point);
1313              
1314             # Find the number of bytes comprising the first character in $text
1315             # (without having to know the details of its internal representation).
1316             # This loop will iterate just once on well-formed input.
1317 3440100         3879378 while ($limit > 0) { # Until we succeed or exhaust the input
1318 4679197         4558571 my $copy = substr($start_point, 0, $limit);
1319              
1320             # decode() will return true if all bytes are valid; false
1321             # if any aren't.
1322 4679197 100       6138657 if (utf8::decode($copy)) {
1323              
1324             # Is valid: get the first character, convert back to bytes,
1325             # and return those bytes.
1326 3440095         5235822 $copy = substr($copy, 0, 1);
1327 3440095         4874857 utf8::encode($copy);
1328 3440095         3031994 $utf8_len = length $copy;
1329 3440095         6024287 return substr($start_point, 0, $utf8_len);
1330             }
1331              
1332             # If it didn't work, it could be that there is a full legal character
1333             # followed by a partial or malformed one. Narrow the window and
1334             # try again.
1335 1239102         1464825 $limit--;
1336             }
1337              
1338             # Failed to find a legal UTF-8 character.
1339 5         30 $utf8_len = 0;
1340 5         23 return;
1341             }
1342              
1343              
1344             sub decode_error {
1345 101     101 0 221 my $error = shift;
1346 101         112 my $no_rep = shift;
1347 101 100       205 my $str = defined $text ? substr($text, $at) : '';
1348 101         135 my $mess = '';
1349 101         147 my $type = 'U*';
1350              
1351 101         106 if ( OLD_PERL ) {
1352             my $type = $] < 5.006 ? 'C*'
1353             : utf8::is_utf8( $str ) ? 'U*' # 5.6
1354             : 'C*'
1355             ;
1356             }
1357              
1358 101         397 for my $c ( unpack( $type, $str ) ) { # emulate pv_uni_display() ?
1359 459         566 my $chr_c = chr($c);
1360 459 50       978 $mess .= $chr_c eq '\\' ? '\\\\'
    50          
    50          
    50          
    50          
    100          
    100          
1361             : $chr_c =~ /[[:print:]]/ ? $chr_c
1362             : $chr_c eq '\a' ? '\a'
1363             : $chr_c eq '\t' ? '\t'
1364             : $chr_c eq '\n' ? '\n'
1365             : $chr_c eq '\r' ? '\r'
1366             : $chr_c eq '\f' ? '\f'
1367             : sprintf('\x{%x}', $c)
1368             ;
1369 459 100       684 if ( length $mess >= 20 ) {
1370 10         16 $mess .= '...';
1371 10         20 last;
1372             }
1373             }
1374              
1375 101 100       210 unless ( length $mess ) {
1376 30         40 $mess = '(end of string)';
1377             }
1378              
1379             Carp::croak (
1380 101 100       25346 $no_rep ? "$error" : "$error, at character offset $at (before \"$mess\")"
1381             );
1382              
1383             }
1384              
1385              
1386             sub _json_object_hook {
1387 9     9   10 my $o = $_[0];
1388 9         8 my @ks = keys %{$o};
  9         21  
1389              
1390 9 100 66     46 if ( $cb_sk_object and @ks == 1 and exists $cb_sk_object->{ $ks[0] } and ref $cb_sk_object->{ $ks[0] } ) {
      100        
      66        
1391 4         8 my @val = $cb_sk_object->{ $ks[0] }->( $o->{$ks[0]} );
1392 4 100       14 if (@val == 0) {
    50          
1393 1         3 return $o;
1394             }
1395             elsif (@val == 1) {
1396 3         9 return $val[0];
1397             }
1398             else {
1399 0         0 Carp::croak("filter_json_single_key_object callbacks must not return more than one scalar");
1400             }
1401             }
1402              
1403 5 100       13 my @val = $cb_object->($o) if ($cb_object);
1404 5 100       14 if (@val == 0) {
    50          
1405 3         7 return $o;
1406             }
1407             elsif (@val == 1) {
1408 2         7 return $val[0];
1409             }
1410             else {
1411 0         0 Carp::croak("filter_json_object callbacks must not return more than one scalar");
1412             }
1413             }
1414              
1415              
1416             sub PP_decode_box {
1417             {
1418 0     0 1 0 text => $text,
1419             at => $at,
1420             ch => $ch,
1421             len => $len,
1422             depth => $depth,
1423             encoding => $encoding,
1424             is_valid_utf8 => $is_valid_utf8,
1425             };
1426             }
1427              
1428             } # PARSE
1429              
1430              
1431             sub _decode_surrogates { # from perlunicode
1432 1127736     1127736   1434212 my $uni = 0x10000 + (hex($_[0]) - 0xD800) * 0x400 + (hex($_[1]) - 0xDC00);
1433 1127736         1569925 my $un = pack('U*', $uni);
1434 1127736         1564345 utf8::encode( $un );
1435 1127736         1703709 return $un;
1436             }
1437              
1438              
1439             sub _decode_unicode {
1440 2893171     2893171   4178928 my $un = pack('U', hex shift);
1441 2893171         4133622 utf8::encode( $un );
1442 2893171         5669902 return $un;
1443             }
1444              
1445             #
1446             # Setup for various Perl versions (the code from JSON::PP58)
1447             #
1448              
1449             BEGIN {
1450              
1451 57 50   57   355 unless ( defined &utf8::is_utf8 ) {
1452 0         0 require Encode;
1453 0         0 *utf8::is_utf8 = *Encode::is_utf8;
1454             }
1455              
1456 57         113 if ( !OLD_PERL ) {
1457 57         176 *JSON::PP::JSON_PP_encode_ascii = \&_encode_ascii;
1458 57         130 *JSON::PP::JSON_PP_encode_latin1 = \&_encode_latin1;
1459 57         100 *JSON::PP::JSON_PP_decode_surrogates = \&_decode_surrogates;
1460 57         95 *JSON::PP::JSON_PP_decode_unicode = \&_decode_unicode;
1461              
1462 57 50       212 if ($] < 5.008003) { # join() in 5.8.0 - 5.8.2 is broken.
1463             package # hide from PAUSE
1464             JSON::PP;
1465 0         0 require subs;
1466 0         0 subs->import('join');
1467 0         0 eval q|
1468             sub join {
1469             return '' if (@_ < 2);
1470             my $j = shift;
1471             my $str = shift;
1472             for (@_) { $str .= $j . $_; }
1473             return $str;
1474             }
1475             |;
1476             }
1477             }
1478              
1479              
1480             sub JSON::PP::incr_parse {
1481 744     744 1 52665 local $Carp::CarpLevel = 1;
1482 744   66     1806 ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_parse( @_ );
1483             }
1484              
1485              
1486             sub JSON::PP::incr_skip {
1487 2   33 2 1 1514 ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_skip;
1488             }
1489              
1490              
1491             sub JSON::PP::incr_reset {
1492 0   0 0 1 0 ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_reset;
1493             }
1494              
1495 57 50 33 304 1 20924 eval q{
  304 50       47021  
  304         546  
  0         0  
  304         1164  
1496             sub JSON::PP::incr_text : lvalue {
1497             $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new;
1498              
1499             if ( $_[0]->{_incr_parser}->{incr_pos} ) {
1500             Carp::croak("incr_text cannot be called when the incremental parser already started parsing");
1501             }
1502             $_[0]->{_incr_parser}->{incr_text};
1503             }
1504             } if ( $] >= 5.006 );
1505              
1506             } # Setup for various Perl versions (the code from JSON::PP58)
1507              
1508              
1509             ###############################
1510             # Utilities
1511             #
1512              
1513             BEGIN {
1514 57     57   3170 eval 'require Scalar::Util';
1515 57 50       382 unless($@){
1516 57         217 *JSON::PP::blessed = \&Scalar::Util::blessed;
1517 57         99 *JSON::PP::reftype = \&Scalar::Util::reftype;
1518 57         4934 *JSON::PP::refaddr = \&Scalar::Util::refaddr;
1519             }
1520             else{ # This code is from Scalar::Util.
1521             # warn $@;
1522 0         0 eval 'sub UNIVERSAL::a_sub_not_likely_to_be_here { ref($_[0]) }';
1523             *JSON::PP::blessed = sub {
1524 0         0 local($@, $SIG{__DIE__}, $SIG{__WARN__});
1525 0 0       0 ref($_[0]) ? eval { $_[0]->a_sub_not_likely_to_be_here } : undef;
  0         0  
1526 0         0 };
1527 0         0 require B;
1528 0         0 my %tmap = qw(
1529             B::NULL SCALAR
1530             B::HV HASH
1531             B::AV ARRAY
1532             B::CV CODE
1533             B::IO IO
1534             B::GV GLOB
1535             B::REGEXP REGEXP
1536             );
1537             *JSON::PP::reftype = sub {
1538 0         0 my $r = shift;
1539              
1540 0 0       0 return undef unless length(ref($r));
1541              
1542 0         0 my $t = ref(B::svref_2object($r));
1543              
1544             return
1545 0 0       0 exists $tmap{$t} ? $tmap{$t}
    0          
1546             : length(ref($$r)) ? 'REF'
1547             : 'SCALAR';
1548 0         0 };
1549             *JSON::PP::refaddr = sub {
1550 0 0       0 return undef unless length(ref($_[0]));
1551              
1552 0         0 my $addr;
1553 0 0       0 if(defined(my $pkg = blessed($_[0]))) {
1554 0         0 $addr .= bless $_[0], 'Scalar::Util::Fake';
1555 0         0 bless $_[0], $pkg;
1556             }
1557             else {
1558 0         0 $addr .= $_[0]
1559             }
1560              
1561 0         0 $addr =~ /0x(\w+)/;
1562 0         0 local $^W;
1563             #no warnings 'portable';
1564 0         0 hex($1);
1565             }
1566 0         0 }
1567             }
1568              
1569              
1570             # shamelessly copied and modified from JSON::XS code.
1571              
1572             $JSON::PP::true = do { bless \(my $dummy = 1), "JSON::PP::Boolean" };
1573             $JSON::PP::false = do { bless \(my $dummy = 0), "JSON::PP::Boolean" };
1574              
1575             sub is_bool {
1576 5 100   5 1 1039 if (blessed $_[0]) {
1577             return (
1578 2   33     17 $_[0]->isa("JSON::PP::Boolean")
1579             or $_[0]->isa("Types::Serialiser::BooleanBase")
1580             or $_[0]->isa("JSON::XS::Boolean")
1581             );
1582             }
1583 0         0 elsif (CORE_BOOL) {
1584 57     57   5270 BEGIN { CORE_BOOL and warnings->unimport('experimental::builtin') }
1585             return builtin::is_bool($_[0]);
1586             }
1587 3         10 return !!0;
1588             }
1589              
1590 0     0 1 0 sub true { $JSON::PP::true }
1591 0     0 1 0 sub false { $JSON::PP::false }
1592 0     0 1 0 sub null { undef; }
1593              
1594             ###############################
1595              
1596             package # hide from PAUSE
1597             JSON::PP::IncrParser;
1598              
1599 57     57   349 use strict;
  57         104  
  57         1507  
1600              
1601 57     57   267 use constant INCR_M_WS => 0; # initial whitespace skipping
  57         85  
  57         3255  
1602 57     57   318 use constant INCR_M_STR => 1; # inside string
  57         93  
  57         2312  
1603 57     57   267 use constant INCR_M_BS => 2; # inside backslash
  57         90  
  57         2286  
1604 57     57   270 use constant INCR_M_JSON => 3; # outside anything, count nesting
  57         102  
  57         2252  
1605 57     57   301 use constant INCR_M_C0 => 4;
  57         107  
  57         2202  
1606 57     57   271 use constant INCR_M_C1 => 5;
  57         90  
  57         2099  
1607 57     57   259 use constant INCR_M_TFN => 6;
  57         78  
  57         2260  
1608 57     57   276 use constant INCR_M_NUM => 7;
  57         90  
  57         14180  
1609              
1610             $JSON::backportPP::IncrParser::VERSION = '1.01';
1611              
1612             sub new {
1613 57     57   87 my ( $class ) = @_;
1614              
1615 57         278 bless {
1616             incr_nest => 0,
1617             incr_text => undef,
1618             incr_pos => 0,
1619             incr_mode => 0,
1620             }, $class;
1621             }
1622              
1623              
1624             sub incr_parse {
1625 744     744   1073 my ( $self, $coder, $text ) = @_;
1626              
1627 744 100       1135 $self->{incr_text} = '' unless ( defined $self->{incr_text} );
1628              
1629 744 100       1030 if ( defined $text ) {
1630 402         773 $self->{incr_text} .= $text;
1631             }
1632              
1633 744 100       1592 if ( defined wantarray ) {
1634 383         537 my $max_size = $coder->get_max_size;
1635 383         471 my $p = $self->{incr_pos};
1636 383         401 my @ret;
1637             {
1638 383         405 do {
  383         385  
1639 394 100 100     1062 unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) {
1640 393         764 $self->_incr_parse( $coder );
1641              
1642 392 100 100     692 if ( $max_size and $self->{incr_pos} > $max_size ) {
1643 1         75 Carp::croak("attempted decode of JSON text of $self->{incr_pos} bytes size, but max_size is set to $max_size");
1644             }
1645 391 100 100     926 unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) {
1646             # as an optimisation, do not accumulate white space in the incr buffer
1647 83 100 100     170 if ( $self->{incr_mode} == INCR_M_WS and $self->{incr_pos} ) {
1648 7         9 $self->{incr_pos} = 0;
1649 7         8 $self->{incr_text} = '';
1650             }
1651 83         102 last;
1652             }
1653             }
1654              
1655 309 100       5873 unless ( $coder->get_utf8 ) {
1656 301         767 utf8::decode( $self->{incr_text} );
1657             }
1658              
1659 309         594 my ($obj, $offset) = $coder->PP_decode_json( $self->{incr_text}, 0x00000001 );
1660 298         427 push @ret, $obj;
1661 57     57   345 use bytes;
  57         75  
  57         258  
1662 298   50     631 $self->{incr_text} = substr( $self->{incr_text}, $offset || 0 );
1663 298         336 $self->{incr_pos} = 0;
1664 298         308 $self->{incr_nest} = 0;
1665 298         273 $self->{incr_mode} = 0;
1666 298 100       524 last unless wantarray;
1667             } while ( wantarray );
1668             }
1669              
1670 370 100       507 if ( wantarray ) {
1671 7         31 return @ret;
1672             }
1673             else { # in scalar context
1674 363 100       1016 return defined $ret[0] ? $ret[0] : undef;
1675             }
1676             }
1677             }
1678              
1679              
1680             sub _incr_parse {
1681 393     393   473 my ($self, $coder) = @_;
1682 393         650 my $text = $self->{incr_text};
1683 393         445 my $len = length $text;
1684 393         448 my $p = $self->{incr_pos};
1685              
1686             INCR_PARSE:
1687 393         558 while ( $len > $p ) {
1688 3084         3320 my $s = substr( $text, $p, 1 );
1689 3084 50       3661 last INCR_PARSE unless defined $s;
1690 3084         2960 my $mode = $self->{incr_mode};
1691              
1692 3084 100 100     8771 if ( $mode == INCR_M_WS ) {
    50          
    100          
    100          
    100          
    100          
    50          
1693 335         464 while ( $len > $p ) {
1694 594         662 $s = substr( $text, $p, 1 );
1695 594 50       731 last INCR_PARSE unless defined $s;
1696 594 100       881 if ( ord($s) > ord " " ) {
1697 328 100       468 if ( $s eq '#' ) {
1698 6         8 $self->{incr_mode} = INCR_M_C0;
1699 6         11 redo INCR_PARSE;
1700             } else {
1701 322         332 $self->{incr_mode} = INCR_M_JSON;
1702 322         493 redo INCR_PARSE;
1703             }
1704             }
1705 266         342 $p++;
1706             }
1707             } elsif ( $mode == INCR_M_BS ) {
1708 0         0 $p++;
1709 0         0 $self->{incr_mode} = INCR_M_STR;
1710 0         0 redo INCR_PARSE;
1711             } elsif ( $mode == INCR_M_C0 or $mode == INCR_M_C1 ) {
1712 9         18 while ( $len > $p ) {
1713 45         49 $s = substr( $text, $p, 1 );
1714 45 50       61 last INCR_PARSE unless defined $s;
1715 45 100       54 if ( $s eq "\n" ) {
1716 9 100       15 $self->{incr_mode} = $self->{incr_mode} == INCR_M_C0 ? INCR_M_WS : INCR_M_JSON;
1717 9         11 last;
1718             }
1719 36         41 $p++;
1720             }
1721 9         14 next;
1722             } elsif ( $mode == INCR_M_TFN ) {
1723 36 50 66     54 last INCR_PARSE if $p >= $len && $self->{incr_nest};
1724 35         43 while ( $len > $p ) {
1725 140         164 $s = substr( $text, $p++, 1 );
1726 140 100 66     358 next if defined $s and $s =~ /[rueals]/;
1727 35         33 last;
1728             }
1729 35         33 $p--;
1730 35         39 $self->{incr_mode} = INCR_M_JSON;
1731              
1732 35 50       49 last INCR_PARSE unless $self->{incr_nest};
1733 35         33 redo INCR_PARSE;
1734             } elsif ( $mode == INCR_M_NUM ) {
1735 399 100 100     614 last INCR_PARSE if $p >= $len && $self->{incr_nest};
1736 396         488 while ( $len > $p ) {
1737 482         509 $s = substr( $text, $p++, 1 );
1738 482 100 66     1164 next if defined $s and $s =~ /[0-9eE.+\-]/;
1739 389         392 last;
1740             }
1741 396         353 $p--;
1742 396         426 $self->{incr_mode} = INCR_M_JSON;
1743              
1744 396 100       507 last INCR_PARSE unless $self->{incr_nest};
1745 378         389 redo INCR_PARSE;
1746             } elsif ( $mode == INCR_M_STR ) {
1747 805         1004 while ( $len > $p ) {
1748 84413         74412 $s = substr( $text, $p, 1 );
1749 84413 50       89451 last INCR_PARSE unless defined $s;
1750 84413 100       104037 if ( $s eq '"' ) {
    100          
1751 780         720 $p++;
1752 780         805 $self->{incr_mode} = INCR_M_JSON;
1753              
1754 780 100       1146 last INCR_PARSE unless $self->{incr_nest};
1755 760         810 redo INCR_PARSE;
1756             }
1757             elsif ( $s eq '\\' ) {
1758 508         455 $p++;
1759 508 50       653 if ( !defined substr($text, $p, 1) ) {
1760 0         0 $self->{incr_mode} = INCR_M_BS;
1761 0         0 last INCR_PARSE;
1762             }
1763             }
1764 83633         88473 $p++;
1765             }
1766             } elsif ( $mode == INCR_M_JSON ) {
1767 1500         1850 while ( $len > $p ) {
1768 3614         3968 $s = substr( $text, $p++, 1 );
1769 3614 50 66     15266 if ( $s eq "\x00" ) {
    100 100        
    100 100        
    100 100        
    100          
    100          
    100          
    100          
1770 0         0 $p--;
1771 0         0 last INCR_PARSE;
1772             } elsif ( $s =~ /^[\t\n\r ]$/) {
1773 724 50       956 if ( !$self->{incr_nest} ) {
1774 0         0 $p--; # do not eat the whitespace, let the next round do it
1775 0         0 last INCR_PARSE;
1776             }
1777 724         903 next;
1778             } elsif ( $s eq 't' or $s eq 'f' or $s eq 'n' ) {
1779 36         38 $self->{incr_mode} = INCR_M_TFN;
1780 36         37 redo INCR_PARSE;
1781             } elsif ( $s =~ /^[0-9\-]$/ ) {
1782 398         479 $self->{incr_mode} = INCR_M_NUM;
1783 398         518 redo INCR_PARSE;
1784             } elsif ( $s eq '"' ) {
1785 783         885 $self->{incr_mode} = INCR_M_STR;
1786 783         902 redo INCR_PARSE;
1787             } elsif ( $s eq '[' or $s eq '{' ) {
1788 383 100       650 if ( ++$self->{incr_nest} > $coder->get_max_depth ) {
1789 1         61 Carp::croak('json text or perl structure exceeds maximum nesting level (max_depth set too low?)');
1790             }
1791 382         608 next;
1792             } elsif ( $s eq ']' or $s eq '}' ) {
1793 369 100       577 if ( --$self->{incr_nest} <= 0 ) {
1794 270         370 last INCR_PARSE;
1795             }
1796             } elsif ( $s eq '#' ) {
1797 3         4 $self->{incr_mode} = INCR_M_C1;
1798 3         4 redo INCR_PARSE;
1799             }
1800             }
1801             }
1802             }
1803              
1804 392         438 $self->{incr_pos} = $p;
1805 392 100       614 $self->{incr_parsing} = $p ? 1 : 0; # for backward compatibility
1806             }
1807              
1808              
1809             sub incr_text {
1810 0 0   0   0 if ( $_[0]->{incr_pos} ) {
1811 0         0 Carp::croak("incr_text cannot be called when the incremental parser already started parsing");
1812             }
1813 0         0 $_[0]->{incr_text};
1814             }
1815              
1816              
1817             sub incr_skip {
1818 2     2   5 my $self = shift;
1819 2         5 $self->{incr_text} = substr( $self->{incr_text}, $self->{incr_pos} );
1820 2         2 $self->{incr_pos} = 0;
1821 2         3 $self->{incr_mode} = 0;
1822 2         3 $self->{incr_nest} = 0;
1823             }
1824              
1825              
1826             sub incr_reset {
1827 0     0     my $self = shift;
1828 0           $self->{incr_text} = undef;
1829 0           $self->{incr_pos} = 0;
1830 0           $self->{incr_mode} = 0;
1831 0           $self->{incr_nest} = 0;
1832             }
1833              
1834             ###############################
1835              
1836              
1837             1;
1838             __END__