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   1228 use 5.005;
  57         165  
7 57     57   264 use strict;
  57         78  
  57         1409  
8              
9 57     57   240 use Exporter ();
  57         90  
  57         1336  
10 57     57   2002 BEGIN { @JSON::backportPP::ISA = ('Exporter') }
11              
12 57     57   55892 use overload ();
  57         48892  
  57         1222  
13 57     57   19126 use JSON::backportPP::Boolean;
  57         708  
  57         1453  
14              
15 57     57   321 use Carp ();
  57         84  
  57         2051  
16             #use Devel::Peek;
17              
18             $JSON::backportPP::VERSION = '4.11';
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   264 use constant P_ASCII => 0;
  57         101  
  57         5708  
26 57     57   323 use constant P_LATIN1 => 1;
  57         111  
  57         2805  
27 57     57   315 use constant P_UTF8 => 2;
  57         92  
  57         2515  
28 57     57   283 use constant P_INDENT => 3;
  57         132  
  57         2332  
29 57     57   293 use constant P_CANONICAL => 4;
  57         110  
  57         2541  
30 57     57   311 use constant P_SPACE_BEFORE => 5;
  57         85  
  57         2586  
31 57     57   282 use constant P_SPACE_AFTER => 6;
  57         111  
  57         2289  
32 57     57   321 use constant P_ALLOW_NONREF => 7;
  57         131  
  57         2475  
33 57     57   285 use constant P_SHRINK => 8;
  57         89  
  57         2180  
34 57     57   274 use constant P_ALLOW_BLESSED => 9;
  57         80  
  57         2702  
35 57     57   306 use constant P_CONVERT_BLESSED => 10;
  57         103  
  57         4891  
36 57     57   275 use constant P_RELAXED => 11;
  57         83  
  57         2348  
37              
38 57     57   288 use constant P_LOOSE => 12;
  57         82  
  57         2336  
39 57     57   281 use constant P_ALLOW_BIGNUM => 13;
  57         78  
  57         2162  
40 57     57   295 use constant P_ALLOW_BAREKEY => 14;
  57         85  
  57         2236  
41 57     57   303 use constant P_ALLOW_SINGLEQUOTE => 15;
  57         81  
  57         2265  
42 57     57   268 use constant P_ESCAPE_SLASH => 16;
  57         85  
  57         2195  
43 57     57   267 use constant P_AS_NONBLESSED => 17;
  57         84  
  57         2110  
44              
45 57     57   297 use constant P_ALLOW_UNKNOWN => 18;
  57         148  
  57         2338  
46 57     57   277 use constant P_ALLOW_TAGS => 19;
  57         98  
  57         3150  
47              
48 57 50   57   329 use constant OLD_PERL => $] < 5.008 ? 1 : 0;
  57         98  
  57         3118  
49 57   50 57   305 use constant USE_B => $ENV{PERL_JSON_PP_USE_B} || 0;
  57         104  
  57         4392  
50 57     57   294 use constant CORE_BOOL => defined &builtin::is_bool;
  57         122  
  57         6127  
51              
52             my $invalid_char_re;
53              
54             BEGIN {
55 57     57   186 $invalid_char_re = "[";
56 57         125 for my $i (0 .. 0x01F, 0x22, 0x5c) { # '/' is ok
57 1938         2469 $invalid_char_re .= quotemeta chr utf8::unicode_to_native($i);
58             }
59              
60 57         2774 $invalid_char_re = qr/$invalid_char_re]/;
61             }
62              
63             BEGIN {
64 57     57   7487 if (USE_B) {
65             require B;
66             }
67             }
68              
69             BEGIN {
70 57     57   330 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         179 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         97 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         132 for my $name (@xs_compati_bit_properties, @pp_bit_properties) {
89 1140         3807 my $property_id = 'P_' . uc($name);
90              
91 1140 50   2 1 140761 eval qq/
  2 50   1 1 561  
  2 50   10 1 7  
  2 50   24704 1 7  
  0 100   1 1 0  
  2 100   2 0 6  
  1 100   3 1 4  
  1 100   0 0 3  
  1 50   12298 1 4  
  0 50   16 1 0  
  1 50   13 1 2  
  10 50   1 1 904  
  10 100   0 0 23  
  7 100   0 0 20  
  3 0   7 0 7  
  10 0   7 0 48  
  24704 100   0 0 87787  
  24704 100   0 0 48654  
  9335 100   0 0 18443  
  15369 100   0 0 29511  
  24704 100   7 0 354544  
  1 100   7 0 986  
  1 50   7 0 4  
  1 50   0 0 5  
  0 0   7 0 0  
  1 0   7 0 3  
  2 100   0 0 29  
  2 100   7 0 4  
  2 0   7 0 6  
  0 0   7 0 0  
  2 0   7 0 19  
  3 0   316 0 790  
  3 100   12 1 7  
  2 100   8 1 7  
  1 100   0 1 4  
  3 0   20 1 6  
  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       33782  
  12298 100       24059  
  12296 100       20220  
  2 100       4  
  12298 100       74659  
  16 100       625  
  16 100       29  
  14 0       33  
  2 0       4  
  16 100       28  
  13 100       550  
  13 100       31  
  10 100       25  
  3 100       7  
  13 100       56  
  1 100       5  
  1 100       3  
  1 100       5  
  0 100       0  
  1         3  
  0         0  
  0         0  
  7         282  
  7         285  
  0         0  
  0         0  
  0         0  
  0         0  
  7         739  
  7         290  
  7         291  
  0         0  
  7         322  
  7         298  
  0         0  
  7         280  
  7         286  
  7         341  
  7         300  
  316         1484  
  12         972  
  12         26  
  8         13  
  4         8  
  12         90  
  8         518  
  8         19  
  6         19  
  2         5  
  8         46  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  20         533  
  20         42  
  18         47  
  2         5  
  20         35  
  21510         62009  
  21510         40037  
  21508         44961  
  2         4  
  21510         65622  
  13         538  
  13         24  
  8         13  
  5         10  
  13         22  
  12         518  
  12         21  
  8         18  
  4         54  
  12         87  
  18457         49972  
  18457         32758  
  18455         31098  
  2         5  
  18457         238314  
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 936 ($JSON ||= __PACKAGE__->new->utf8)->encode(@_);
121             }
122              
123              
124             sub decode_json { # decode
125 6206   66 6206 1 66977 ($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 2358244 my $class = shift;
144 43174         117617 my $self = {
145             max_depth => 512,
146             max_size => 0,
147             indent_length => 3,
148             };
149              
150 43174         96263 $self->{PROPS}[P_ALLOW_NONREF] = 1;
151              
152 43174         972919 bless $self, $class;
153             }
154              
155              
156             sub encode {
157 25163     25163 1 123592 return $_[0]->PP_encode_json($_[1]);
158             }
159              
160              
161             sub decode {
162 24967     24967 1 111781 return $_[0]->PP_decode_json($_[1], 0x00000000);
163             }
164              
165              
166             sub decode_prefix {
167 8     8 1 694 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 2056 my ($self, $v) = @_;
178 5 50       13 my $enable = defined $v ? $v : 1;
179              
180 5 100       10 if ($enable) { # indent_length(3) for JSON::XS compatibility
181 3         60 $self->indent(1)->space_before(1)->space_after(1);
182             }
183             else {
184 2         41 $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 729 my $max = defined $_[1] ? $_[1] : 0x80000000;
194 7         15 $_[0]->{max_depth} = $max;
195 7         36 $_[0];
196             }
197              
198              
199 386     386 0 880 sub get_max_depth { $_[0]->{max_depth}; }
200              
201              
202             sub max_size {
203 5 100   5 1 292 my $max = defined $_[1] ? $_[1] : 0;
204 5         8 $_[0]->{max_size} = $max;
205 5         10 $_[0];
206             }
207              
208              
209 386     386 0 589 sub get_max_size { $_[0]->{max_size}; }
210              
211             sub boolean_values {
212 10     10 0 2871 my $self = shift;
213 10 100       22 if (@_) {
214 5         8 my ($false, $true) = @_;
215 5         9 $self->{false} = $false;
216 5         10 $self->{true} = $true;
217 5         6 if (CORE_BOOL) {
218 57     57   88556 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         49 delete $self->{false};
228 5         8 delete $self->{true};
229 5         6 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 4106 my $self = shift;
267 10 50 66     34 if (exists $self->{true} and exists $self->{false}) {
268 5         15 return @$self{qw/false true/};
269             }
270 5         14 return;
271             }
272              
273             sub filter_json_object {
274 3 100 66 3 1 14 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     10 $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0;
280 3         6 $_[0];
281             }
282              
283             sub filter_json_single_key_object {
284 4 50 33 4 1 17 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     11 if (defined $_[2] and ref $_[2] eq 'CODE') {
288 3         19 $_[0]->{cb_sk_object}->{$_[1]} = $_[2];
289             } else {
290 1         4 delete $_[0]->{cb_sk_object}->{$_[1]};
291 1 50       2 delete $_[0]->{cb_sk_object} unless %{$_[0]->{cb_sk_object} || {}};
  1 50       18  
292             }
293 4 50 33     15 $_[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 1855 $_[0]->{sort_by} = defined $_[1] ? $_[1] : 1;
313 3         16 $_[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 34088 my $self = shift;
354 25163         27914 my $obj = shift;
355              
356 25163         30815 $indent_count = 0;
357 25163         28427 $depth = 0;
358              
359 25163         37003 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         49981 = @{$props}[P_ASCII .. P_SPACE_AFTER, P_ALLOW_BLESSED, P_CONVERT_BLESSED,
  25163         82128  
364             P_ESCAPE_SLASH, P_ALLOW_BIGNUM, P_AS_NONBLESSED, P_ALLOW_TAGS];
365              
366 25163         33877 ($max_depth, $indent_length) = @{$self}{qw/max_depth indent_length/};
  25163         42902  
367              
368 25163 100   587   53360 $keysort = $canonical ? sub { $a cmp $b } : undef;
  587         1021  
369              
370 25163 100       55777 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   22 : sub { $a cmp $b };
  18 100       24  
374             }
375              
376 25163 50 66     62127 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         54645 my $str = $self->object_to_json($obj);
380              
381 25145 100       54973 $str .= "\n" if ( $indent ); # JSON::XS 2.26 compatible
382              
383 25145         75045 return $str;
384             }
385              
386              
387             sub object_to_json {
388 25523     25523 0 40697 my ($self, $obj) = @_;
389 25523         38862 my $type = ref($obj);
390              
391 25523 100       64642 if($type eq 'HASH'){
    100          
    100          
392 348         628 return $self->hash_to_json($obj);
393             }
394             elsif($type eq 'ARRAY'){
395 25021         55219 return $self->array_to_json($obj);
396             }
397             elsif ($type) { # blessed object?
398 67 100       194 if (blessed($obj)) {
399              
400 47 100       222 return $self->value_to_json($obj) if ( $obj->isa('JSON::PP::Boolean') );
401              
402 19 100 100     66 if ( $allow_tags and $obj->can('FREEZE') ) {
403 1   33     3 my $obj_class = ref $obj || $obj;
404 1         3 $obj = bless $obj, $obj_class;
405 1         3 my @results = $obj->FREEZE('JSON');
406 1 50 33     885 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         7 return '("'.$obj_class.'")['.join(',', @results).']';
415             }
416              
417 18 100 100     93 if ( $convert_blessed and $obj->can('TO_JSON') ) {
418 9         51 my $result = $obj->TO_JSON();
419 9 100 66     737 if ( defined $result and ref( $result ) ) {
420 4 100       29 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         41 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       11 if ($allow_blessed) {
434 4 50       8 return $self->blessed_to_json($obj) if ($as_nonblessed); # will be removed.
435 4         10 return 'null';
436             }
437 2         12 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         46 return $self->value_to_json($obj);
442             }
443             }
444             else{
445 87         189 return $self->value_to_json($obj);
446             }
447             }
448              
449              
450             sub hash_to_json {
451 348     348 0 438 my ($self, $obj) = @_;
452 348         381 my @res;
453              
454 348 100       567 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       633 my ($pre, $post) = $indent ? $self->_up_indent() : ('', '');
458 347 100       751 my $del = ($space_before ? ' ' : '') . ':' . ($space_after ? ' ' : '');
    100          
459              
460 347         536 for my $k ( _sort( $obj ) ) {
461 746         849 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       1134 . ( ref $obj->{$k} ? $self->object_to_json( $obj->{$k} ) : $self->value_to_json( $obj->{$k} ) );
465             }
466              
467 345         506 --$depth;
468 345 100       513 $self->_down_indent() if ($indent);
469              
470 345 100       621 return '{}' unless @res;
471 335         1312 return '{' . $pre . join( ",$pre", @res ) . $post . '}';
472             }
473              
474              
475             sub array_to_json {
476 25021     25021 0 39739 my ($self, $obj) = @_;
477 25021         34865 my @res;
478              
479 25021 100       50705 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       55443 my ($pre, $post) = $indent ? $self->_up_indent() : ('', '');
483              
484 25020         52725 for my $v (@$obj){
485 25812 100       70869 push @res, ref($v) ? $self->object_to_json($v) : $self->value_to_json($v);
486             }
487              
488 25006         37370 --$depth;
489 25006 100       44464 $self->_down_indent() if ($indent);
490              
491 25006 100       51179 return '[]' unless @res;
492 24996         180456 return '[' . $pre . join( ",$pre", @res ) . $post . ']';
493             }
494              
495             sub _looks_like_number {
496 26248     26248   35954 my $value = shift;
497 26248         31544 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   522 no warnings 'numeric';
  57         114  
  57         8160  
504             # if the utf8 flag is on, it almost certainly started as a string
505 26248 100       86449 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       54662 return unless length((my $dummy = "") & $value);
511 828 100       1497 return unless 0 + $value eq $value;
512 825 50       1990 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 47503 my ($self, $value) = @_;
519              
520 26341 100       46076 return 'null' if(!defined $value);
521              
522 26296         35896 my $type = ref($value);
523              
524 26296 100 66     45938 if (!$type) {
    100          
525 57     57   53666 BEGIN { CORE_BOOL and warnings->unimport('experimental::builtin') }
526 26248 100       53230 if (CORE_BOOL && builtin::is_bool($value)) {
527             return $value ? 'true' : 'false';
528             }
529 0         0 elsif (_looks_like_number($value)) {
530 825         1877 return $value;
531             }
532 25423         62549 return $self->string_to_json($value);
533             }
534             elsif( blessed($value) and $value->isa('JSON::PP::Boolean') ){
535 28 100       169 return $$value == 1 ? 'true' : 'false';
536             }
537             else {
538 20 50       53 if ((overload::StrVal($value) =~ /=(\w+)/)[0]) {
539 0         0 return $self->value_to_json("$value");
540             }
541              
542 20 100 100     152 if ($type eq 'SCALAR' and defined $$value) {
543             return $$value eq '1' ? 'true'
544             : $$value eq '0' ? 'false'
545 7 100       52 : $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ? 'null'
    100          
    100          
546             : encode_error("cannot encode reference to scalar");
547             }
548              
549 13 100       29 if ( $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ) {
550 4         10 return 'null';
551             }
552             else {
553 9 100 100     36 if ( $type eq 'SCALAR' or $type eq 'REF' ) {
554 6         29 encode_error("cannot encode reference to scalar");
555             }
556             else {
557 3         17 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 52982 my ($self, $arg) = @_;
579              
580 26169         415052 $arg =~ s/(["\\\n\r\t\f\b])/$esc{$1}/g;
581 26169 100       52141 $arg =~ s/\//\\\//g if ($escape_slash);
582              
583             # On ASCII platforms, matches [\x00-\x08\x0b\x0e-\x1f]
584 26169         142516 $arg =~ s/([^\n\t\c?[:^cntrl:][:^ascii:]])/'\\u00' . unpack('H2', $1)/eg;
  580660         1258832  
585              
586 26169 100       45559 if ($ascii) {
587 12297         27606 $arg = JSON_PP_encode_ascii($arg);
588             }
589              
590 26169 100       163859 if ($latin1) {
591 2         4 $arg = JSON_PP_encode_latin1($arg);
592             }
593              
594 26169 100       49475 if ($utf8) {
595 12551         46468 utf8::encode($arg);
596             }
597              
598 26169         211484 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 29 my $error = shift;
618 18         1921 Carp::croak "$error";
619             }
620              
621              
622             sub _sort {
623 347 100   347   472 defined $keysort ? (sort $keysort (keys %{$_[0]})) : keys %{$_[0]};
  222         962  
  125         448  
624             }
625              
626              
627             sub _up_indent {
628 9     9   12 my $self = shift;
629 9         15 my $space = ' ' x $indent_length;
630              
631 9         14 my ($pre,$post) = ('','');
632              
633 9         12 $post = "\n" . $space x $indent_count;
634              
635 9         10 $indent_count++;
636              
637 9         12 $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   278886 chr($_) =~ /[[:ascii:]]/ ?
  6264941 100       12991930  
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   9 $_ <= 255 ?
  22 100       45  
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   1181397 my $uni = $_[0] - 0x10000;
682 1127735         2589925 return ($uni / 0x400 + 0xD800, $uni % 0x400 + 0xDC00);
683             }
684              
685              
686             sub _is_bignum {
687 3 100   3   16 $_[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   245 my $checkint = 1111;
700 57         242 for my $d (5..64) {
701 969         1363 $checkint .= 1;
702 969         26047 my $int = eval qq| $checkint |;
703 969 100       3785 if ($int =~ /[eE]/) {
704 57         122 $max_intsize = $d - 1;
705 57         21150 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   19821 my $text = shift;
753 12410         34194 my @octets = unpack('C4', $text);
754 12410 100       26576 return 'unknown' unless defined $octets[3];
755 12390 0 100     48198 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 36585 my ($self, $want_offset);
765              
766 25284         61063 ($self, $text, $want_offset) = @_;
767              
768 25284         49115 ($at, $ch, $depth) = (0, '', 0);
769              
770 25284 100 100     98860 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         41013 my $props = $self->{PROPS};
775              
776             ($utf8, $relaxed, $loose, $allow_bignum, $allow_barekey, $singlequote, $allow_tags)
777 25280         42770 = @{$props}[P_UTF8, P_RELAXED, P_LOOSE .. P_ALLOW_SINGLEQUOTE, P_ALLOW_TAGS];
  25280         62579  
778              
779 25280         52810 ($alt_true, $alt_false) = @$self{qw/true false/};
780              
781 25280 100       45982 if ( $utf8 ) {
782 12410         23059 $encoding = _detect_utf_encoding($text);
783 12410 100 100     32984 if ($encoding ne 'UTF-8' and $encoding ne 'unknown') {
784 3         559 require Encode;
785 3         8031 Encode::from_to($text, $encoding, 'utf-8');
786             } else {
787 12407 100       32811 utf8::downgrade( $text, 1 ) or Carp::croak("Wide character in subroutine entry");
788             }
789             }
790             else {
791 12870         49238 utf8::encode( $text );
792             }
793              
794 25279         37124 $len = length $text;
795              
796             ($max_depth, $max_size, $cb_object, $cb_sk_object, $F_HOOK)
797 25279         32538 = @{$self}{qw/max_depth max_size cb_object cb_sk_object F_HOOK/};
  25279         57313  
798              
799 25279 100       52862 if ($max_size > 1) {
800 57     57   30860 use bytes;
  57         698  
  57         255  
801 2         4 my $bytes = length $text;
802 2 100       17 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         59126 white(); # remove head white space
809              
810 25278 100       44272 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         45956 my $result = value();
813              
814 25199 100 100     88285 if ( !$props->[ P_ALLOW_NONREF ] and !ref $result ) {
815 5         24 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       42107 Carp::croak('something wrong.') if $len < $at; # we won't arrive here.
821              
822 25194 100       41356 my $consumed = defined $ch ? $at - 1 : $at; # consumed JSON text length
823              
824 25194         44831 white(); # remove tail white space
825              
826 25194 100       41726 return ( $result, $consumed ) if $want_offset; # all right if decode_prefix
827              
828 24890 100       37892 decode_error("garbage after JSON object") if defined $ch;
829              
830 24878         186257 $result;
831             }
832              
833              
834             sub next_chr {
835 36724965 100   36724965 0 45507437 return $ch = undef if($at >= $len);
836 36699880         53023665 $ch = substr($text, $at++, 1);
837             }
838              
839              
840             sub value {
841 53854     53854 0 85265 white();
842 53854 50       79506 return if(!defined $ch);
843 53854 100       85251 return object() if($ch eq '{');
844 52464 100       105459 return array() if($ch eq '[');
845 26345 100       57231 return tag() if($ch eq '(');
846 26344 100 66     60766 return string() if($ch eq '"' or ($singlequote and $ch eq "'"));
      100        
847 921 100 100     2634 return number() if($ch =~ /[0-9]/ or $ch eq '-');
848 109         178 return word();
849             }
850              
851             sub string {
852 27153     27153 1 39876 my $utf16;
853             my $is_utf8;
854              
855 27153         52250 ($is_valid_utf8, $utf8_len) = ('', 0);
856              
857 27153         34145 my $s = ''; # basically UTF8 flag on
858              
859 27153 100 66     51191 if($ch eq '"' or ($singlequote and $ch eq "'")){
      100        
860 27148         31981 my $boundChar = $ch;
861              
862 27148         33910 OUTER: while( defined(next_chr()) ){
863              
864 10715253 100       17053289 if($ch eq $boundChar){
    100          
865 27132         60991 next_chr();
866              
867 27132 100       37855 if ($utf16) {
868 1         3 decode_error("missing low surrogate character in surrogate pair");
869             }
870              
871 27131 100       110030 utf8::decode($s) if($is_utf8);
872              
873 27131         113855 return $s;
874             }
875             elsif($ch eq '\\'){
876 5302031         7193520 next_chr();
877 5302031 100       7739866 if(exists $escapes{$ch}){
    100          
878 153380         241405 $s .= $escapes{$ch};
879             }
880             elsif($ch eq 'u'){ # UNICODE handling
881 5148647         5214343 my $u = '';
882              
883 5148647         5930666 for(1..4){
884 20594588         21972906 $ch = next_chr();
885 20594588 50       38506338 last OUTER if($ch !~ /[0-9a-fA-F]/);
886 20594588         24672389 $u .= $ch;
887             }
888              
889             # U+D800 - U+DBFF
890 5148647 100       9294583 if ($u =~ /^[dD][89abAB][0-9a-fA-F]{2}/) { # UTF-16 high surrogate?
    100          
891 1127738         1574410 $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       1464684 unless (defined $utf16) {
896 1         5 decode_error("missing high surrogate character in surrogate pair");
897             }
898 1127736         1069576 $is_utf8 = 1;
899 1127736   50     1365935 $s .= JSON_PP_decode_surrogates($utf16, $u) || next;
900 1127736         1719877 $utf16 = undef;
901             }
902             else {
903 2893172 100       3712035 if (defined $utf16) {
904 1         3 decode_error("surrogate pair expected");
905             }
906              
907 2893171         3155593 my $hex = hex( $u );
908 2893171 50       3940181 if ( chr $u =~ /[[:^ascii:]]/ ) {
909 2893171         2662504 $is_utf8 = 1;
910 2893171   50     3431094 $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       7 unless ($loose) {
920 4         4 $at -= 2;
921 4         7 decode_error('illegal backslash escape sequence in string');
922             }
923 0         0 $s .= $ch;
924             }
925             }
926             else{
927              
928 5386090 100       9074445 if ( $ch =~ /[[:^ascii:]]/ ) {
929 3440100 100       4109367 unless( $ch = is_valid_utf8($ch) ) {
930 5         10 $at -= 1;
931 5         11 decode_error("malformed UTF-8 character in JSON string");
932             }
933             else {
934 3440095         3843607 $at += $utf8_len - 1;
935             }
936              
937 3440095         3630165 $is_utf8 = 1;
938             }
939              
940 5386085 50       6747851 if (!$loose) {
941 5386085 100       11800521 if ($ch =~ $invalid_char_re) { # '/' ok
942 4 50 33     14 if (!$relaxed or $ch ne "\t") {
943 4         7 $at--;
944 4         20 decode_error(sprintf "invalid character 0x%X"
945             . " encountered while parsing JSON string",
946             ord $ch);
947             }
948             }
949             }
950              
951 5386081         7218860 $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 260217 while( defined $ch ){
962 164785 100 100     514383 if($ch eq '' or $ch =~ /\A[ \t\r\n]\z/){
    50 66        
963 27684         47283 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     212832 if ($relaxed and $ch eq '#') { # correctly?
997 9         30 pos($text) = $at;
998 9         34 $text =~ /\G([^\n]*(?:\r\n|\r|\n|$))/g;
999 9         15 $at = pos($text);
1000 9         16 next_chr;
1001 9         13 next;
1002             }
1003              
1004 137092         162508 last;
1005             }
1006             }
1007             }
1008              
1009              
1010             sub array {
1011 26119   50 26119 1 71899 my $a = $_[0] || []; # you can use this code to use another array ref object.
1012              
1013 26119 100       52094 decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
1014             if (++$depth > $max_depth);
1015              
1016 26116         44494 next_chr();
1017 26116         50455 white();
1018              
1019 26116 100 66     68619 if(defined $ch and $ch eq ']'){
1020 23         36 --$depth;
1021 23         42 next_chr();
1022 23         46 return $a;
1023             }
1024             else {
1025 26093         51263 while(defined($ch)){
1026 26852         47409 push @$a, value();
1027              
1028 26285         58389 white();
1029              
1030 26285 100       51242 if (!defined $ch) {
1031 3         6 last;
1032             }
1033              
1034 26282 100       43535 if($ch eq ']'){
1035 25518         29738 --$depth;
1036 25518         41696 next_chr();
1037 25518         54757 return $a;
1038             }
1039              
1040 764 100       1027 if($ch ne ','){
1041 3         4 last;
1042             }
1043              
1044 761         1199 next_chr();
1045 761         1133 white();
1046              
1047 761 100 100     1447 if ($relaxed and $ch eq ']') {
1048 2         12 --$depth;
1049 2         4 next_chr();
1050 2         14 return $a;
1051             }
1052              
1053             }
1054             }
1055              
1056 6 100 66     27 $at-- if defined $ch and $ch ne '';
1057 6         11 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         6 my $tag = value();
1067 1 50       2 return unless defined $tag;
1068 1 50       3 decode_error('malformed JSON string, (tag) must be a string') if ref $tag;
1069              
1070 1         2 white();
1071              
1072 1 50 33     4 if (!defined $ch or $ch ne ')') {
1073 0         0 decode_error(') expected after tag');
1074             }
1075              
1076 1         3 next_chr();
1077 1         2 white();
1078              
1079 1         8 my $val = value();
1080 1 50       2 return unless defined $val;
1081 1 50       4 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         4 $tag->THAW('JSON', @$val);
1088             }
1089              
1090             sub object {
1091 1390   50 1390 1 3225 my $o = $_[0] || {}; # you can use this code to use another hash ref object.
1092 1390         1599 my $k;
1093              
1094 1390 50       1977 decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
1095             if (++$depth > $max_depth);
1096 1390         2030 next_chr();
1097 1390         2023 white();
1098              
1099 1390 100 66     3045 if(defined $ch and $ch eq '}'){
1100 9         14 --$depth;
1101 9         19 next_chr();
1102 9 100       29 if ($F_HOOK) {
1103 1         4 return _json_object_hook($o);
1104             }
1105 8         17 return $o;
1106             }
1107             else {
1108 1381         1875 while (defined $ch) {
1109 1732 100 66     3381 $k = ($allow_barekey and $ch ne '"' and $ch ne "'") ? bareKey() : string();
1110 1727         2668 white();
1111              
1112 1727 100 100     4082 if(!defined $ch or $ch ne ':'){
1113 3         6 $at--;
1114 3         21 decode_error("':' expected");
1115             }
1116              
1117 1724         2719 next_chr();
1118 1724         2288 $o->{$k} = value();
1119 1207         2034 white();
1120              
1121 1207 100       1605 last if (!defined $ch);
1122              
1123 1205 100       1713 if($ch eq '}'){
1124 847         799 --$depth;
1125 847         1724 next_chr();
1126 847 100       1204 if ($F_HOOK) {
1127 8         12 return _json_object_hook($o);
1128             }
1129 839         1701 return $o;
1130             }
1131              
1132 358 100       551 if($ch ne ','){
1133 5         9 last;
1134             }
1135              
1136 353         536 next_chr();
1137 353         538 white();
1138              
1139 353 100 66     723 if ($relaxed and $ch eq '}') {
1140 1         1 --$depth;
1141 1         2 next_chr();
1142 1 50       2 if ($F_HOOK) {
1143 0         0 return _json_object_hook($o);
1144             }
1145 1         14 return $o;
1146             }
1147              
1148             }
1149              
1150             }
1151              
1152 8 100 66     34 $at-- if defined $ch and $ch ne '';
1153 8         22 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 4 my $key;
1159 2         11 while($ch =~ /[\$\w[:^ascii:]]/){
1160 6         9 $key .= $ch;
1161 6         10 next_chr();
1162             }
1163 2         5 return $key;
1164             }
1165              
1166              
1167             sub word {
1168 109     109 0 194 my $word = substr($text,$at-1,4);
1169              
1170 109 100       402 if($word eq 'true'){
    100          
    100          
1171 21         27 $at += 3;
1172 21         37 next_chr;
1173 21 100       53 return defined $alt_true ? $alt_true : $JSON::PP::true;
1174             }
1175             elsif($word eq 'null'){
1176 46         53 $at += 3;
1177 46         86 next_chr;
1178 46         106 return undef;
1179             }
1180             elsif($word eq 'fals'){
1181 18         42 $at += 3;
1182 18 50       47 if(substr($text,$at,1) eq 'e'){
1183 18         25 $at++;
1184 18         31 next_chr;
1185 18 100       42 return defined $alt_false ? $alt_false : $JSON::PP::false;
1186             }
1187             }
1188              
1189 24         30 $at--; # for decode_error report
1190              
1191 24 100       98 decode_error("'null' expected") if ($word =~ /^n/);
1192 23 100       72 decode_error("'true' expected") if ($word =~ /^t/);
1193 22 50       51 decode_error("'false' expected") if ($word =~ /^f/);
1194 22         106 decode_error("malformed JSON string, neither array, object, number, string or atom");
1195             }
1196              
1197              
1198             sub number {
1199 812     812 1 997 my $n = '';
1200 812         1363 my $v;
1201             my $is_dec;
1202 812         0 my $is_exp;
1203              
1204 812 100       1336 if($ch eq '-'){
1205 41         55 $n = '-';
1206 41         92 next_chr;
1207 41 100 66     190 if (!defined $ch or $ch !~ /\d/) {
1208 1         2 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       1187 if($ch eq '0'){
1214 46         91 my $peek = substr($text,$at,1);
1215 46 100       95 if($peek =~ /^[0-9a-dfA-DF]/){ # e may be valid (exponential)
1216 5         9 decode_error("malformed number (leading zero must not be followed by another digit)");
1217             }
1218 41         56 $n .= $ch;
1219 41         49 next_chr;
1220             }
1221              
1222 806   100     2467 while(defined $ch and $ch =~ /\d/){
1223 971         1159 $n .= $ch;
1224 971         1180 next_chr;
1225             }
1226              
1227 806 100 100     2011 if(defined $ch and $ch eq '.'){
1228 49         68 $n .= '.';
1229 49         57 $is_dec = 1;
1230              
1231 49         85 next_chr;
1232 49 100 66     173 if (!defined $ch or $ch !~ /\d/) {
1233 1         2 decode_error("malformed number (no digits after decimal point)");
1234             }
1235             else {
1236 48         120 $n .= $ch;
1237             }
1238              
1239 48   100     72 while(defined(next_chr) and $ch =~ /\d/){
1240 97         153 $n .= $ch;
1241             }
1242             }
1243              
1244 805 100 100     2406 if(defined $ch and ($ch eq 'e' or $ch eq 'E')){
      100        
1245 58         69 $n .= $ch;
1246 58         60 $is_exp = 1;
1247 58         127 next_chr;
1248              
1249 58 100 100     240 if(defined($ch) and ($ch eq '+' or $ch eq '-')){
    100 100        
      100        
1250 38         53 $n .= $ch;
1251 38         122 next_chr;
1252 38 100 66     122 if (!defined $ch or $ch =~ /\D/) {
1253 2         4 decode_error("malformed number (no digits after exp sign)");
1254             }
1255 36         46 $n .= $ch;
1256             }
1257             elsif(defined($ch) and $ch =~ /\d/){
1258 18         34 $n .= $ch;
1259             }
1260             else {
1261 2         11 decode_error("malformed number (no digits after exp sign)");
1262             }
1263              
1264 54   100     69 while(defined(next_chr) and $ch =~ /\d/){
1265 33         57 $n .= $ch;
1266             }
1267              
1268             }
1269              
1270 801         967 $v .= $n;
1271              
1272 801 100 100     1713 if ($is_dec or $is_exp) {
1273 70 100       112 if ($allow_bignum) {
1274 1         3272 require Math::BigFloat;
1275 1         22489 return Math::BigFloat->new($v);
1276             }
1277             } else {
1278 731 100       1138 if (length $v > $max_intsize) {
1279 1 50       3 if ($allow_bignum) { # from Adam Sussman
1280 1         7 require Math::BigInt;
1281 1         4 return Math::BigInt->new($v);
1282             }
1283             else {
1284 0         0 return "$v";
1285             }
1286             }
1287             }
1288              
1289 799 100       2131 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   178994 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 5514773 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         3469408 my $limit = $max_unicode_length;
1312 3440100 100       4666500 $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         4437650 while ($limit > 0) { # Until we succeed or exhaust the input
1318 4679197         5136811 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       7092400 if (utf8::decode($copy)) {
1323              
1324             # Is valid: get the first character, convert back to bytes,
1325             # and return those bytes.
1326 3440095         5853683 $copy = substr($copy, 0, 1);
1327 3440095         5305492 utf8::encode($copy);
1328 3440095         3299543 $utf8_len = length $copy;
1329 3440095         6482740 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         1656787 $limit--;
1336             }
1337              
1338             # Failed to find a legal UTF-8 character.
1339 5         10 $utf8_len = 0;
1340 5         39 return;
1341             }
1342              
1343              
1344             sub decode_error {
1345 101     101 0 158 my $error = shift;
1346 101         199 my $no_rep = shift;
1347 101 100       238 my $str = defined $text ? substr($text, $at) : '';
1348 101         128 my $mess = '';
1349 101         146 my $type = 'U*';
1350              
1351 101         136 if ( OLD_PERL ) {
1352             my $type = $] < 5.006 ? 'C*'
1353             : utf8::is_utf8( $str ) ? 'U*' # 5.6
1354             : 'C*'
1355             ;
1356             }
1357              
1358 101         435 for my $c ( unpack( $type, $str ) ) { # emulate pv_uni_display() ?
1359 459         607 my $chr_c = chr($c);
1360 459 50       1176 $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       803 if ( length $mess >= 20 ) {
1370 10         15 $mess .= '...';
1371 10         15 last;
1372             }
1373             }
1374              
1375 101 100       232 unless ( length $mess ) {
1376 30         44 $mess = '(end of string)';
1377             }
1378              
1379             Carp::croak (
1380 101 100       26598 $no_rep ? "$error" : "$error, at character offset $at (before \"$mess\")"
1381             );
1382              
1383             }
1384              
1385              
1386             sub _json_object_hook {
1387 9     9   12 my $o = $_[0];
1388 9         11 my @ks = keys %{$o};
  9         23  
1389              
1390 9 100 66     48 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         12 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         10 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       11 my @val = $cb_object->($o) if ($cb_object);
1404 5 100       16 if (@val == 0) {
    50          
1405 3         9 return $o;
1406             }
1407             elsif (@val == 1) {
1408 2         8 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   1615126 my $uni = 0x10000 + (hex($_[0]) - 0xD800) * 0x400 + (hex($_[1]) - 0xDC00);
1433 1127736         1752338 my $un = pack('U*', $uni);
1434 1127736         1749742 utf8::encode( $un );
1435 1127736         1898433 return $un;
1436             }
1437              
1438              
1439             sub _decode_unicode {
1440 2893171     2893171   4425304 my $un = pack('U', hex shift);
1441 2893171         4481555 utf8::encode( $un );
1442 2893171         6293610 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   415 unless ( defined &utf8::is_utf8 ) {
1452 0         0 require Encode;
1453 0         0 *utf8::is_utf8 = *Encode::is_utf8;
1454             }
1455              
1456 57         117 if ( !OLD_PERL ) {
1457 57         202 *JSON::PP::JSON_PP_encode_ascii = \&_encode_ascii;
1458 57         135 *JSON::PP::JSON_PP_encode_latin1 = \&_encode_latin1;
1459 57         117 *JSON::PP::JSON_PP_decode_surrogates = \&_decode_surrogates;
1460 57         115 *JSON::PP::JSON_PP_decode_unicode = \&_decode_unicode;
1461              
1462 57 50       264 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 43779 local $Carp::CarpLevel = 1;
1482 744   66     1948 ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_parse( @_ );
1483             }
1484              
1485              
1486             sub JSON::PP::incr_skip {
1487 2   33 2 1 1323 ( $_[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 22988 eval q{
  304 50       38682  
  304         594  
  0         0  
  304         1346  
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   3435 eval 'require Scalar::Util';
1515 57 50       1836 unless($@){
1516 57         225 *JSON::PP::blessed = \&Scalar::Util::blessed;
1517 57         115 *JSON::PP::reftype = \&Scalar::Util::reftype;
1518 57         5395 *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 738 if (blessed $_[0]) {
1577             return (
1578 2   33     15 $_[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   5687 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   393 use strict;
  57         115  
  57         1626  
1600              
1601 57     57   287 use constant INCR_M_WS => 0; # initial whitespace skipping
  57         119  
  57         3444  
1602 57     57   291 use constant INCR_M_STR => 1; # inside string
  57         110  
  57         2639  
1603 57     57   305 use constant INCR_M_BS => 2; # inside backslash
  57         102  
  57         2463  
1604 57     57   310 use constant INCR_M_JSON => 3; # outside anything, count nesting
  57         110  
  57         2428  
1605 57     57   297 use constant INCR_M_C0 => 4;
  57         132  
  57         2454  
1606 57     57   280 use constant INCR_M_C1 => 5;
  57         102  
  57         2303  
1607 57     57   316 use constant INCR_M_TFN => 6;
  57         95  
  57         2367  
1608 57     57   316 use constant INCR_M_NUM => 7;
  57         105  
  57         15218  
1609              
1610             $JSON::backportPP::IncrParser::VERSION = '1.01';
1611              
1612             sub new {
1613 57     57   91 my ( $class ) = @_;
1614              
1615 57         346 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   1159 my ( $self, $coder, $text ) = @_;
1626              
1627 744 100       1278 $self->{incr_text} = '' unless ( defined $self->{incr_text} );
1628              
1629 744 100       1197 if ( defined $text ) {
1630 402         840 $self->{incr_text} .= $text;
1631             }
1632              
1633 744 100       1649 if ( defined wantarray ) {
1634 383         675 my $max_size = $coder->get_max_size;
1635 383         503 my $p = $self->{incr_pos};
1636 383         474 my @ret;
1637             {
1638 383         416 do {
  383         416  
1639 394 100 100     1217 unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) {
1640 393         805 $self->_incr_parse( $coder );
1641              
1642 392 100 100     770 if ( $max_size and $self->{incr_pos} > $max_size ) {
1643 1         87 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     1095 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     207 if ( $self->{incr_mode} == INCR_M_WS and $self->{incr_pos} ) {
1648 7         11 $self->{incr_pos} = 0;
1649 7         11 $self->{incr_text} = '';
1650             }
1651 83         116 last;
1652             }
1653             }
1654              
1655 309 100       6640 unless ( $coder->get_utf8 ) {
1656 301         851 utf8::decode( $self->{incr_text} );
1657             }
1658              
1659 309         690 my ($obj, $offset) = $coder->PP_decode_json( $self->{incr_text}, 0x00000001 );
1660 298         655 push @ret, $obj;
1661 57     57   396 use bytes;
  57         89  
  57         234  
1662 298   50     668 $self->{incr_text} = substr( $self->{incr_text}, $offset || 0 );
1663 298         368 $self->{incr_pos} = 0;
1664 298         344 $self->{incr_nest} = 0;
1665 298         362 $self->{incr_mode} = 0;
1666 298 100       571 last unless wantarray;
1667             } while ( wantarray );
1668             }
1669              
1670 370 100       562 if ( wantarray ) {
1671 7         46 return @ret;
1672             }
1673             else { # in scalar context
1674 363 100       1178 return defined $ret[0] ? $ret[0] : undef;
1675             }
1676             }
1677             }
1678              
1679              
1680             sub _incr_parse {
1681 393     393   497 my ($self, $coder) = @_;
1682 393         714 my $text = $self->{incr_text};
1683 393         485 my $len = length $text;
1684 393         440 my $p = $self->{incr_pos};
1685              
1686             INCR_PARSE:
1687 393         632 while ( $len > $p ) {
1688 3084         3797 my $s = substr( $text, $p, 1 );
1689 3084 50       4078 last INCR_PARSE unless defined $s;
1690 3084         3162 my $mode = $self->{incr_mode};
1691              
1692 3084 100 100     9755 if ( $mode == INCR_M_WS ) {
    50          
    100          
    100          
    100          
    100          
    50          
1693 335         509 while ( $len > $p ) {
1694 594         734 $s = substr( $text, $p, 1 );
1695 594 50       763 last INCR_PARSE unless defined $s;
1696 594 100       940 if ( ord($s) > ord " " ) {
1697 328 100       497 if ( $s eq '#' ) {
1698 6         9 $self->{incr_mode} = INCR_M_C0;
1699 6         11 redo INCR_PARSE;
1700             } else {
1701 322         361 $self->{incr_mode} = INCR_M_JSON;
1702 322         535 redo INCR_PARSE;
1703             }
1704             }
1705 266         402 $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         19 while ( $len > $p ) {
1713 45         49 $s = substr( $text, $p, 1 );
1714 45 50       61 last INCR_PARSE unless defined $s;
1715 45 100       61 if ( $s eq "\n" ) {
1716 9 100       17 $self->{incr_mode} = $self->{incr_mode} == INCR_M_C0 ? INCR_M_WS : INCR_M_JSON;
1717 9         11 last;
1718             }
1719 36         47 $p++;
1720             }
1721 9         17 next;
1722             } elsif ( $mode == INCR_M_TFN ) {
1723 36 50 66     76 last INCR_PARSE if $p >= $len && $self->{incr_nest};
1724 35         53 while ( $len > $p ) {
1725 140         200 $s = substr( $text, $p++, 1 );
1726 140 100 66     417 next if defined $s and $s =~ /[rueals]/;
1727 35         39 last;
1728             }
1729 35         35 $p--;
1730 35         43 $self->{incr_mode} = INCR_M_JSON;
1731              
1732 35 50       53 last INCR_PARSE unless $self->{incr_nest};
1733 35         42 redo INCR_PARSE;
1734             } elsif ( $mode == INCR_M_NUM ) {
1735 399 100 100     593 last INCR_PARSE if $p >= $len && $self->{incr_nest};
1736 396         538 while ( $len > $p ) {
1737 482         563 $s = substr( $text, $p++, 1 );
1738 482 100 66     1246 next if defined $s and $s =~ /[0-9eE.+\-]/;
1739 389         487 last;
1740             }
1741 396         390 $p--;
1742 396         468 $self->{incr_mode} = INCR_M_JSON;
1743              
1744 396 100       584 last INCR_PARSE unless $self->{incr_nest};
1745 378         458 redo INCR_PARSE;
1746             } elsif ( $mode == INCR_M_STR ) {
1747 805         1130 while ( $len > $p ) {
1748 84413         80766 $s = substr( $text, $p, 1 );
1749 84413 50       93613 last INCR_PARSE unless defined $s;
1750 84413 100       114591 if ( $s eq '"' ) {
    100          
1751 780         769 $p++;
1752 780         893 $self->{incr_mode} = INCR_M_JSON;
1753              
1754 780 100       1117 last INCR_PARSE unless $self->{incr_nest};
1755 760         861 redo INCR_PARSE;
1756             }
1757             elsif ( $s eq '\\' ) {
1758 508         554 $p++;
1759 508 50       714 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         95007 $p++;
1765             }
1766             } elsif ( $mode == INCR_M_JSON ) {
1767 1500         2108 while ( $len > $p ) {
1768 3614         4275 $s = substr( $text, $p++, 1 );
1769 3614 50 66     16866 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       1053 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         965 next;
1778             } elsif ( $s eq 't' or $s eq 'f' or $s eq 'n' ) {
1779 36         48 $self->{incr_mode} = INCR_M_TFN;
1780 36         43 redo INCR_PARSE;
1781             } elsif ( $s =~ /^[0-9\-]$/ ) {
1782 398         494 $self->{incr_mode} = INCR_M_NUM;
1783 398         546 redo INCR_PARSE;
1784             } elsif ( $s eq '"' ) {
1785 783         939 $self->{incr_mode} = INCR_M_STR;
1786 783         877 redo INCR_PARSE;
1787             } elsif ( $s eq '[' or $s eq '{' ) {
1788 383 100       795 if ( ++$self->{incr_nest} > $coder->get_max_depth ) {
1789 1         73 Carp::croak('json text or perl structure exceeds maximum nesting level (max_depth set too low?)');
1790             }
1791 382         620 next;
1792             } elsif ( $s eq ']' or $s eq '}' ) {
1793 369 100       733 if ( --$self->{incr_nest} <= 0 ) {
1794 270         374 last INCR_PARSE;
1795             }
1796             } elsif ( $s eq '#' ) {
1797 3         5 $self->{incr_mode} = INCR_M_C1;
1798 3         6 redo INCR_PARSE;
1799             }
1800             }
1801             }
1802             }
1803              
1804 392         466 $self->{incr_pos} = $p;
1805 392 100       762 $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         3 $self->{incr_pos} = 0;
1821 2         3 $self->{incr_mode} = 0;
1822 2         5 $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__