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   1140 use 5.005;
  57         158  
7 57     57   237 use strict;
  57         84  
  57         934  
8              
9 57     57   213 use Exporter ();
  57         79  
  57         1334  
10 57     57   1839 BEGIN { @JSON::backportPP::ISA = ('Exporter') }
11              
12 57     57   54085 use overload ();
  57         46354  
  57         1169  
13 57     57   18383 use JSON::backportPP::Boolean;
  57         647  
  57         1392  
14              
15 57     57   284 use Carp ();
  57         86  
  57         2081  
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   263 use constant P_ASCII => 0;
  57         88  
  57         5236  
26 57     57   301 use constant P_LATIN1 => 1;
  57         96  
  57         2668  
27 57     57   305 use constant P_UTF8 => 2;
  57         100  
  57         2736  
28 57     57   293 use constant P_INDENT => 3;
  57         129  
  57         2292  
29 57     57   275 use constant P_CANONICAL => 4;
  57         104  
  57         2390  
30 57     57   272 use constant P_SPACE_BEFORE => 5;
  57         79  
  57         2565  
31 57     57   274 use constant P_SPACE_AFTER => 6;
  57         103  
  57         2305  
32 57     57   306 use constant P_ALLOW_NONREF => 7;
  57         109  
  57         2356  
33 57     57   313 use constant P_SHRINK => 8;
  57         84  
  57         2216  
34 57     57   253 use constant P_ALLOW_BLESSED => 9;
  57         94  
  57         2925  
35 57     57   306 use constant P_CONVERT_BLESSED => 10;
  57         95  
  57         4523  
36 57     57   268 use constant P_RELAXED => 11;
  57         83  
  57         2274  
37              
38 57     57   282 use constant P_LOOSE => 12;
  57         75  
  57         2349  
39 57     57   335 use constant P_ALLOW_BIGNUM => 13;
  57         78  
  57         2432  
40 57     57   256 use constant P_ALLOW_BAREKEY => 14;
  57         78  
  57         2181  
41 57     57   283 use constant P_ALLOW_SINGLEQUOTE => 15;
  57         81  
  57         2140  
42 57     57   254 use constant P_ESCAPE_SLASH => 16;
  57         90  
  57         2073  
43 57     57   260 use constant P_AS_NONBLESSED => 17;
  57         73  
  57         2038  
44              
45 57     57   287 use constant P_ALLOW_UNKNOWN => 18;
  57         135  
  57         2144  
46 57     57   272 use constant P_ALLOW_TAGS => 19;
  57         84  
  57         3050  
47              
48 57 50   57   318 use constant OLD_PERL => $] < 5.008 ? 1 : 0;
  57         98  
  57         3029  
49 57   50 57   281 use constant USE_B => $ENV{PERL_JSON_PP_USE_B} || 0;
  57         101  
  57         4204  
50 57     57   290 use constant CORE_BOOL => defined &builtin::is_bool;
  57         98  
  57         5802  
51              
52             my $invalid_char_re;
53              
54             BEGIN {
55 57     57   190 $invalid_char_re = "[";
56 57         128 for my $i (0 .. 0x01F, 0x22, 0x5c) { # '/' is ok
57 1938         2320 $invalid_char_re .= quotemeta chr utf8::unicode_to_native($i);
58             }
59              
60 57         2644 $invalid_char_re = qr/$invalid_char_re]/;
61             }
62              
63             BEGIN {
64 57     57   7233 if (USE_B) {
65             require B;
66             }
67             }
68              
69             BEGIN {
70 57     57   295 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         173 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         80 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         118 for my $name (@xs_compati_bit_properties, @pp_bit_properties) {
89 1140         3698 my $property_id = 'P_' . uc($name);
90              
91 1140 50   2 1 135238 eval qq/
  2 50   1 1 816  
  2 50   10 1 6  
  2 50   24704 1 10  
  0 100   1 1 0  
  2 100   2 0 5  
  1 100   3 1 4  
  1 100   0 0 3  
  1 50   12298 1 3  
  0 50   16 1 0  
  1 50   13 1 3  
  10 50   1 1 758  
  10 100   0 0 24  
  7 100   0 0 19  
  3 0   7 0 7  
  10 0   7 0 43  
  24704 100   0 0 86759  
  24704 100   0 0 49748  
  9335 100   0 0 17974  
  15369 100   0 0 28358  
  24704 100   7 0 355783  
  1 100   7 0 768  
  1 50   7 0 4  
  1 50   0 0 4  
  0 0   7 0 0  
  1 0   7 0 2  
  2 100   0 0 29  
  2 100   7 0 5  
  2 0   7 0 4  
  0 0   7 0 0  
  2 0   7 0 17  
  3 0   316 0 603  
  3 100   12 1 6  
  2 100   8 1 5  
  1 100   0 1 4  
  3 0   20 1 5  
  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       33710  
  12298 100       21336  
  12296 100       19852  
  2 100       5  
  12298 100       76079  
  16 100       606  
  16 100       44  
  14 0       28  
  2 0       5  
  16 100       33  
  13 100       506  
  13 100       29  
  10 100       27  
  3 100       8  
  13 100       51  
  1 100       5  
  1 100       3  
  1 100       3  
  0 100       0  
  1         3  
  0         0  
  0         0  
  7         267  
  7         265  
  0         0  
  0         0  
  0         0  
  0         0  
  7         710  
  7         1050  
  7         277  
  0         0  
  7         269  
  7         288  
  0         0  
  7         259  
  7         266  
  7         277  
  7         285  
  316         1449  
  12         1027  
  12         45  
  8         18  
  4         16  
  12         97  
  8         462  
  8         17  
  6         15  
  2         5  
  8         43  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  20         518  
  20         35  
  18         36  
  2         7  
  20         34  
  21510         62226  
  21510         38695  
  21508         50311  
  2         5  
  21510         67189  
  13         469  
  13         20  
  8         15  
  5         9  
  13         22  
  12         467  
  12         22  
  8         18  
  4         46  
  12         90  
  18457         49020  
  18457         33265  
  18455         30584  
  2         4  
  18457         239781  
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 1049 ($JSON ||= __PACKAGE__->new->utf8)->encode(@_);
121             }
122              
123              
124             sub decode_json { # decode
125 6206   66 6206 1 67637 ($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 2228329 my $class = shift;
144 43174         120794 my $self = {
145             max_depth => 512,
146             max_size => 0,
147             indent_length => 3,
148             };
149              
150 43174         94752 $self->{PROPS}[P_ALLOW_NONREF] = 1;
151              
152 43174         927271 bless $self, $class;
153             }
154              
155              
156             sub encode {
157 25163     25163 1 131531 return $_[0]->PP_encode_json($_[1]);
158             }
159              
160              
161             sub decode {
162 24967     24967 1 109121 return $_[0]->PP_decode_json($_[1], 0x00000000);
163             }
164              
165              
166             sub decode_prefix {
167 8     8 1 741 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 2514 my ($self, $v) = @_;
178 5 50       13 my $enable = defined $v ? $v : 1;
179              
180 5 100       8 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         12 $self;
188             }
189              
190             # etc
191              
192             sub max_depth {
193 7 100   7 1 939 my $max = defined $_[1] ? $_[1] : 0x80000000;
194 7         15 $_[0]->{max_depth} = $max;
195 7         41 $_[0];
196             }
197              
198              
199 386     386 0 915 sub get_max_depth { $_[0]->{max_depth}; }
200              
201              
202             sub max_size {
203 5 100   5 1 387 my $max = defined $_[1] ? $_[1] : 0;
204 5         9 $_[0]->{max_size} = $max;
205 5         12 $_[0];
206             }
207              
208              
209 386     386 0 530 sub get_max_size { $_[0]->{max_size}; }
210              
211             sub boolean_values {
212 10     10 0 3111 my $self = shift;
213 10 100       22 if (@_) {
214 5         8 my ($false, $true) = @_;
215 5         10 $self->{false} = $false;
216 5         8 $self->{true} = $true;
217 5         5 if (CORE_BOOL) {
218 57     57   85731 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         40 delete $self->{false};
228 5         6 delete $self->{true};
229 5         7 delete $self->{core_bools};
230             }
231 10         15 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 4302 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         15 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         3 $_[0]->{cb_object} = $_[1];
276             } else {
277 1         2 delete $_[0]->{cb_object};
278             }
279 3 50 66     11 $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0;
280 3         3 $_[0];
281             }
282              
283             sub filter_json_single_key_object {
284 4 50 33 4 1 18 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     20 if (defined $_[2] and ref $_[2] eq 'CODE') {
288 3         9 $_[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       19  
292             }
293 4 50 33     12 $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0;
294 4         6 $_[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 1400 $_[0]->{sort_by} = defined $_[1] ? $_[1] : 1;
313 3         9 $_[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 43353 my $self = shift;
354 25163         32569 my $obj = shift;
355              
356 25163         30779 $indent_count = 0;
357 25163         30101 $depth = 0;
358              
359 25163         37529 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         40037 = @{$props}[P_ASCII .. P_SPACE_AFTER, P_ALLOW_BLESSED, P_CONVERT_BLESSED,
  25163         80732  
364             P_ESCAPE_SLASH, P_ALLOW_BIGNUM, P_AS_NONBLESSED, P_ALLOW_TAGS];
365              
366 25163         38735 ($max_depth, $indent_length) = @{$self}{qw/max_depth indent_length/};
  25163         46923  
367              
368 25163 100   596   48335 $keysort = $canonical ? sub { $a cmp $b } : undef;
  596         992  
369              
370 25163 100       52981 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   21   14 : sub { $a cmp $b };
  21 100       23  
374             }
375              
376 25163 50 66     56718 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         47482 my $str = $self->object_to_json($obj);
380              
381 25145 100       51861 $str .= "\n" if ( $indent ); # JSON::XS 2.26 compatible
382              
383 25145         71757 return $str;
384             }
385              
386              
387             sub object_to_json {
388 25523     25523 0 42358 my ($self, $obj) = @_;
389 25523         38895 my $type = ref($obj);
390              
391 25523 100       71439 if($type eq 'HASH'){
    100          
    100          
392 348         643 return $self->hash_to_json($obj);
393             }
394             elsif($type eq 'ARRAY'){
395 25021         53766 return $self->array_to_json($obj);
396             }
397             elsif ($type) { # blessed object?
398 67 100       192 if (blessed($obj)) {
399              
400 47 100       223 return $self->value_to_json($obj) if ( $obj->isa('JSON::PP::Boolean') );
401              
402 19 100 100     64 if ( $allow_tags and $obj->can('FREEZE') ) {
403 1   33     3 my $obj_class = ref $obj || $obj;
404 1         1 $obj = bless $obj, $obj_class;
405 1         3 my @results = $obj->FREEZE('JSON');
406 1 50 33     813 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     88 if ( $convert_blessed and $obj->can('TO_JSON') ) {
418 9         50 my $result = $obj->TO_JSON();
419 9 100 66     725 if ( defined $result and ref( $result ) ) {
420 4 100       20 if ( refaddr( $obj ) eq refaddr( $result ) ) {
421 1         8 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         36 return $self->object_to_json( $result );
429             }
430              
431 9 100 66     19 return "$obj" if ( $bignum and _is_bignum($obj) );
432              
433 6 100       13 if ($allow_blessed) {
434 4 50       7 return $self->blessed_to_json($obj) if ($as_nonblessed); # will be removed.
435 4         10 return 'null';
436             }
437 2         11 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         41 return $self->value_to_json($obj);
442             }
443             }
444             else{
445 87         178 return $self->value_to_json($obj);
446             }
447             }
448              
449              
450             sub hash_to_json {
451 348     348 0 483 my ($self, $obj) = @_;
452 348         349 my @res;
453              
454 348 100       561 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       610 my ($pre, $post) = $indent ? $self->_up_indent() : ('', '');
458 347 100       764 my $del = ($space_before ? ' ' : '') . ':' . ($space_after ? ' ' : '');
    100          
459              
460 347         540 for my $k ( _sort( $obj ) ) {
461 746         811 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       1105 . ( ref $obj->{$k} ? $self->object_to_json( $obj->{$k} ) : $self->value_to_json( $obj->{$k} ) );
465             }
466              
467 345         478 --$depth;
468 345 100       523 $self->_down_indent() if ($indent);
469              
470 345 100       578 return '{}' unless @res;
471 335         1349 return '{' . $pre . join( ",$pre", @res ) . $post . '}';
472             }
473              
474              
475             sub array_to_json {
476 25021     25021 0 38629 my ($self, $obj) = @_;
477 25021         32686 my @res;
478              
479 25021 100       45287 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       51601 my ($pre, $post) = $indent ? $self->_up_indent() : ('', '');
483              
484 25020         42692 for my $v (@$obj){
485 25812 100       68075 push @res, ref($v) ? $self->object_to_json($v) : $self->value_to_json($v);
486             }
487              
488 25006         34625 --$depth;
489 25006 100       41913 $self->_down_indent() if ($indent);
490              
491 25006 100       56589 return '[]' unless @res;
492 24996         169384 return '[' . $pre . join( ",$pre", @res ) . $post . ']';
493             }
494              
495             sub _looks_like_number {
496 26248     26248   34442 my $value = shift;
497 26248         33575 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   449 no warnings 'numeric';
  57         119  
  57         7669  
504             # if the utf8 flag is on, it almost certainly started as a string
505 26248 100       75788 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       54330 return unless length((my $dummy = "") & $value);
511 828 100       1469 return unless 0 + $value eq $value;
512 825 50       1967 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 40265 my ($self, $value) = @_;
519              
520 26341 100       42604 return 'null' if(!defined $value);
521              
522 26296         37760 my $type = ref($value);
523              
524 26296 100 66     46022 if (!$type) {
    100          
525 57     57   51163 BEGIN { CORE_BOOL and warnings->unimport('experimental::builtin') }
526 26248 100       46543 if (CORE_BOOL && builtin::is_bool($value)) {
527             return $value ? 'true' : 'false';
528             }
529 0         0 elsif (_looks_like_number($value)) {
530 825         1765 return $value;
531             }
532 25423         62399 return $self->string_to_json($value);
533             }
534             elsif( blessed($value) and $value->isa('JSON::PP::Boolean') ){
535 28 100       189 return $$value == 1 ? 'true' : 'false';
536             }
537             else {
538 20 50       46 if ((overload::StrVal($value) =~ /=(\w+)/)[0]) {
539 0         0 return $self->value_to_json("$value");
540             }
541              
542 20 100 100     138 if ($type eq 'SCALAR' and defined $$value) {
543             return $$value eq '1' ? 'true'
544             : $$value eq '0' ? 'false'
545 7 100       45 : $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ? 'null'
    100          
    100          
546             : encode_error("cannot encode reference to scalar");
547             }
548              
549 13 100       25 if ( $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ) {
550 4         9 return 'null';
551             }
552             else {
553 9 100 100     30 if ( $type eq 'SCALAR' or $type eq 'REF' ) {
554 6         10 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 46362 my ($self, $arg) = @_;
579              
580 26169         411914 $arg =~ s/(["\\\n\r\t\f\b])/$esc{$1}/g;
581 26169 100       52992 $arg =~ s/\//\\\//g if ($escape_slash);
582              
583             # On ASCII platforms, matches [\x00-\x08\x0b\x0e-\x1f]
584 26169         142417 $arg =~ s/([^\n\t\c?[:^cntrl:][:^ascii:]])/'\\u00' . unpack('H2', $1)/eg;
  580660         1501664  
585              
586 26169 100       55568 if ($ascii) {
587 12297         26726 $arg = JSON_PP_encode_ascii($arg);
588             }
589              
590 26169 100       160853 if ($latin1) {
591 2         3 $arg = JSON_PP_encode_latin1($arg);
592             }
593              
594 26169 100       44493 if ($utf8) {
595 12551         45381 utf8::encode($arg);
596             }
597              
598 26169         200380 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 28 my $error = shift;
618 18         1716 Carp::croak "$error";
619             }
620              
621              
622             sub _sort {
623 347 100   347   513 defined $keysort ? (sort $keysort (keys %{$_[0]})) : keys %{$_[0]};
  222         869  
  125         402  
624             }
625              
626              
627             sub _up_indent {
628 9     9   10 my $self = shift;
629 9         16 my $space = ' ' x $indent_length;
630              
631 9         12 my ($pre,$post) = ('','');
632              
633 9         14 $post = "\n" . $space x $indent_count;
634              
635 9         10 $indent_count++;
636              
637 9         13 $pre = "\n" . $space x $indent_count;
638              
639 9         17 return ($pre,$post);
640             }
641              
642              
643 9     9   12 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   274335 chr($_) =~ /[[:ascii:]]/ ?
  6264941 100       15045494  
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       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   1212262 my $uni = $_[0] - 0x10000;
682 1127735         2747215 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   198 my $checkint = 1111;
700 57         179 for my $d (5..64) {
701 969         1369 $checkint .= 1;
702 969         24672 my $int = eval qq| $checkint |;
703 969 100       3789 if ($int =~ /[eE]/) {
704 57         111 $max_intsize = $d - 1;
705 57         20146 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   20291 my $text = shift;
753 12410         35637 my @octets = unpack('C4', $text);
754 12410 100       27282 return 'unknown' unless defined $octets[3];
755 12390 0 100     49015 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 38174 my ($self, $want_offset);
765              
766 25284         62497 ($self, $text, $want_offset) = @_;
767              
768 25284         44478 ($at, $ch, $depth) = (0, '', 0);
769              
770 25284 100 100     92813 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         41225 my $props = $self->{PROPS};
775              
776             ($utf8, $relaxed, $loose, $allow_bignum, $allow_barekey, $singlequote, $allow_tags)
777 25280         42208 = @{$props}[P_UTF8, P_RELAXED, P_LOOSE .. P_ALLOW_SINGLEQUOTE, P_ALLOW_TAGS];
  25280         60872  
778              
779 25280         54209 ($alt_true, $alt_false) = @$self{qw/true false/};
780              
781 25280 100       40099 if ( $utf8 ) {
782 12410         22460 $encoding = _detect_utf_encoding($text);
783 12410 100 100     31475 if ($encoding ne 'UTF-8' and $encoding ne 'unknown') {
784 3         543 require Encode;
785 3         8063 Encode::from_to($text, $encoding, 'utf-8');
786             } else {
787 12407 100       32902 utf8::downgrade( $text, 1 ) or Carp::croak("Wide character in subroutine entry");
788             }
789             }
790             else {
791 12870         50071 utf8::encode( $text );
792             }
793              
794 25279         40389 $len = length $text;
795              
796             ($max_depth, $max_size, $cb_object, $cb_sk_object, $F_HOOK)
797 25279         35039 = @{$self}{qw/max_depth max_size cb_object cb_sk_object F_HOOK/};
  25279         52575  
798              
799 25279 100       46719 if ($max_size > 1) {
800 57     57   29011 use bytes;
  57         666  
  57         239  
801 2         3 my $bytes = length $text;
802 2 100       15 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         54690 white(); # remove head white space
809              
810 25278 100       39524 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         38951 my $result = value();
813              
814 25199 100 100     78194 if ( !$props->[ P_ALLOW_NONREF ] and !ref $result ) {
815 5         25 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       45921 Carp::croak('something wrong.') if $len < $at; # we won't arrive here.
821              
822 25194 100       38538 my $consumed = defined $ch ? $at - 1 : $at; # consumed JSON text length
823              
824 25194         46480 white(); # remove tail white space
825              
826 25194 100       40003 return ( $result, $consumed ) if $want_offset; # all right if decode_prefix
827              
828 24890 100       35955 decode_error("garbage after JSON object") if defined $ch;
829              
830 24878         162874 $result;
831             }
832              
833              
834             sub next_chr {
835 36724965 100   36724965 0 47022688 return $ch = undef if($at >= $len);
836 36699880         53251279 $ch = substr($text, $at++, 1);
837             }
838              
839              
840             sub value {
841 53854     53854 0 80737 white();
842 53854 50       78066 return if(!defined $ch);
843 53854 100       83944 return object() if($ch eq '{');
844 52464 100       92511 return array() if($ch eq '[');
845 26345 100       47114 return tag() if($ch eq '(');
846 26344 100 66     64836 return string() if($ch eq '"' or ($singlequote and $ch eq "'"));
      100        
847 921 100 100     2554 return number() if($ch =~ /[0-9]/ or $ch eq '-');
848 109         185 return word();
849             }
850              
851             sub string {
852 27153     27153 1 34320 my $utf16;
853             my $is_utf8;
854              
855 27153         41670 ($is_valid_utf8, $utf8_len) = ('', 0);
856              
857 27153         34715 my $s = ''; # basically UTF8 flag on
858              
859 27153 100 66     52708 if($ch eq '"' or ($singlequote and $ch eq "'")){
      100        
860 27148         29885 my $boundChar = $ch;
861              
862 27148         33468 OUTER: while( defined(next_chr()) ){
863              
864 10715253 100       17129116 if($ch eq $boundChar){
    100          
865 27132         51335 next_chr();
866              
867 27132 100       39139 if ($utf16) {
868 1         4 decode_error("missing low surrogate character in surrogate pair");
869             }
870              
871 27131 100       110051 utf8::decode($s) if($is_utf8);
872              
873 27131         111191 return $s;
874             }
875             elsif($ch eq '\\'){
876 5302031         7189235 next_chr();
877 5302031 100       7739640 if(exists $escapes{$ch}){
    100          
878 153380         226521 $s .= $escapes{$ch};
879             }
880             elsif($ch eq 'u'){ # UNICODE handling
881 5148647         5127188 my $u = '';
882              
883 5148647         6281349 for(1..4){
884 20594588         21978949 $ch = next_chr();
885 20594588 50       42810957 last OUTER if($ch !~ /[0-9a-fA-F]/);
886 20594588         25020730 $u .= $ch;
887             }
888              
889             # U+D800 - U+DBFF
890 5148647 100       10596227 if ($u =~ /^[dD][89abAB][0-9a-fA-F]{2}/) { # UTF-16 high surrogate?
    100          
891 1127738         1652467 $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       1525231 unless (defined $utf16) {
896 1         4 decode_error("missing high surrogate character in surrogate pair");
897             }
898 1127736         1069291 $is_utf8 = 1;
899 1127736   50     1335805 $s .= JSON_PP_decode_surrogates($utf16, $u) || next;
900 1127736         1735631 $utf16 = undef;
901             }
902             else {
903 2893172 100       3923883 if (defined $utf16) {
904 1         3 decode_error("surrogate pair expected");
905             }
906              
907 2893171         3321991 my $hex = hex( $u );
908 2893171 50       4517160 if ( chr $u =~ /[[:^ascii:]]/ ) {
909 2893171         2822817 $is_utf8 = 1;
910 2893171   50     3379708 $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       10 unless ($loose) {
920 4         6 $at -= 2;
921 4         14 decode_error('illegal backslash escape sequence in string');
922             }
923 0         0 $s .= $ch;
924             }
925             }
926             else{
927              
928 5386090 100       10548546 if ( $ch =~ /[[:^ascii:]]/ ) {
929 3440100 100       4142703 unless( $ch = is_valid_utf8($ch) ) {
930 5         10 $at -= 1;
931 5         12 decode_error("malformed UTF-8 character in JSON string");
932             }
933             else {
934 3440095         3904203 $at += $utf8_len - 1;
935             }
936              
937 3440095         3761467 $is_utf8 = 1;
938             }
939              
940 5386085 50       6864091 if (!$loose) {
941 5386085 100       13059141 if ($ch =~ $invalid_char_re) { # '/' ok
942 4 50 33     11 if (!$relaxed or $ch ne "\t") {
943 4         5 $at--;
944 4         28 decode_error(sprintf "invalid character 0x%X"
945             . " encountered while parsing JSON string",
946             ord $ch);
947             }
948             }
949             }
950              
951 5386081         7634991 $s .= $ch;
952             }
953             }
954             }
955              
956 6         16 decode_error("unexpected end of string while parsing JSON string");
957             }
958              
959              
960             sub white {
961 162168     162168 0 259441 while( defined $ch ){
962 164785 100 100     526726 if($ch eq '' or $ch =~ /\A[ \t\r\n]\z/){
    50 66        
963 27684         40967 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     209900 if ($relaxed and $ch eq '#') { # correctly?
997 9         19 pos($text) = $at;
998 9         26 $text =~ /\G([^\n]*(?:\r\n|\r|\n|$))/g;
999 9         11 $at = pos($text);
1000 9         16 next_chr;
1001 9         14 next;
1002             }
1003              
1004 137092         162378 last;
1005             }
1006             }
1007             }
1008              
1009              
1010             sub array {
1011 26119   50 26119 1 69600 my $a = $_[0] || []; # you can use this code to use another array ref object.
1012              
1013 26119 100       45134 decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
1014             if (++$depth > $max_depth);
1015              
1016 26116         47772 next_chr();
1017 26116         42637 white();
1018              
1019 26116 100 66     69792 if(defined $ch and $ch eq ']'){
1020 23         34 --$depth;
1021 23         46 next_chr();
1022 23         50 return $a;
1023             }
1024             else {
1025 26093         45158 while(defined($ch)){
1026 26852         49716 push @$a, value();
1027              
1028 26285         54850 white();
1029              
1030 26285 100       45657 if (!defined $ch) {
1031 3         6 last;
1032             }
1033              
1034 26282 100       50978 if($ch eq ']'){
1035 25518         27166 --$depth;
1036 25518         44062 next_chr();
1037 25518         55200 return $a;
1038             }
1039              
1040 764 100       1040 if($ch ne ','){
1041 3         4 last;
1042             }
1043              
1044 761         1059 next_chr();
1045 761         1044 white();
1046              
1047 761 100 100     1264 if ($relaxed and $ch eq ']') {
1048 2         3 --$depth;
1049 2         11 next_chr();
1050 2         9 return $a;
1051             }
1052              
1053             }
1054             }
1055              
1056 6 100 66     21 $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 3 decode_error('malformed JSON string, neither array, object, number, string or atom') unless $allow_tags;
1062              
1063 1         3 next_chr();
1064 1         4 white();
1065              
1066 1         3 my $tag = value();
1067 1 50       11 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     4 if (!defined $ch or $ch ne ')') {
1073 0         0 decode_error(') expected after tag');
1074             }
1075              
1076 1         2 next_chr();
1077 1         2 white();
1078              
1079 1         8 my $val = value();
1080 1 50       2 return unless defined $val;
1081 1 50       2 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         4  
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 3290 my $o = $_[0] || {}; # you can use this code to use another hash ref object.
1092 1390         1591 my $k;
1093              
1094 1390 50       2155 decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
1095             if (++$depth > $max_depth);
1096 1390         2171 next_chr();
1097 1390         2101 white();
1098              
1099 1390 100 66     3455 if(defined $ch and $ch eq '}'){
1100 9         15 --$depth;
1101 9         17 next_chr();
1102 9 100       30 if ($F_HOOK) {
1103 1         3 return _json_object_hook($o);
1104             }
1105 8         18 return $o;
1106             }
1107             else {
1108 1381         1990 while (defined $ch) {
1109 1732 100 66     3536 $k = ($allow_barekey and $ch ne '"' and $ch ne "'") ? bareKey() : string();
1110 1727         2720 white();
1111              
1112 1727 100 100     4292 if(!defined $ch or $ch ne ':'){
1113 3         5 $at--;
1114 3         6 decode_error("':' expected");
1115             }
1116              
1117 1724         2678 next_chr();
1118 1724         2259 $o->{$k} = value();
1119 1207         2146 white();
1120              
1121 1207 100       1650 last if (!defined $ch);
1122              
1123 1205 100       1795 if($ch eq '}'){
1124 847         919 --$depth;
1125 847         1289 next_chr();
1126 847 100       1165 if ($F_HOOK) {
1127 8         12 return _json_object_hook($o);
1128             }
1129 839         1617 return $o;
1130             }
1131              
1132 358 100       562 if($ch ne ','){
1133 5         8 last;
1134             }
1135              
1136 353         557 next_chr();
1137 353         534 white();
1138              
1139 353 100 66     801 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         13 return $o;
1146             }
1147              
1148             }
1149              
1150             }
1151              
1152 8 100 66     34 $at-- if defined $ch and $ch ne '';
1153 8         26 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 5 my $key;
1159 2         13 while($ch =~ /[\$\w[:^ascii:]]/){
1160 6         10 $key .= $ch;
1161 6         7 next_chr();
1162             }
1163 2         8 return $key;
1164             }
1165              
1166              
1167             sub word {
1168 109     109 0 214 my $word = substr($text,$at-1,4);
1169              
1170 109 100       376 if($word eq 'true'){
    100          
    100          
1171 21         26 $at += 3;
1172 21         36 next_chr;
1173 21 100       53 return defined $alt_true ? $alt_true : $JSON::PP::true;
1174             }
1175             elsif($word eq 'null'){
1176 46         57 $at += 3;
1177 46         90 next_chr;
1178 46         110 return undef;
1179             }
1180             elsif($word eq 'fals'){
1181 18         33 $at += 3;
1182 18 50       33 if(substr($text,$at,1) eq 'e'){
1183 18         22 $at++;
1184 18         32 next_chr;
1185 18 100       42 return defined $alt_false ? $alt_false : $JSON::PP::false;
1186             }
1187             }
1188              
1189 24         33 $at--; # for decode_error report
1190              
1191 24 100       92 decode_error("'null' expected") if ($word =~ /^n/);
1192 23 100       75 decode_error("'true' expected") if ($word =~ /^t/);
1193 22 50       61 decode_error("'false' expected") if ($word =~ /^f/);
1194 22         114 decode_error("malformed JSON string, neither array, object, number, string or atom");
1195             }
1196              
1197              
1198             sub number {
1199 812     812 1 968 my $n = '';
1200 812         1351 my $v;
1201             my $is_dec;
1202 812         0 my $is_exp;
1203              
1204 812 100       1208 if($ch eq '-'){
1205 41         56 $n = '-';
1206 41         74 next_chr;
1207 41 100 66     180 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       1105 if($ch eq '0'){
1214 46         70 my $peek = substr($text,$at,1);
1215 46 100       86 if($peek =~ /^[0-9a-dfA-DF]/){ # e may be valid (exponential)
1216 5         10 decode_error("malformed number (leading zero must not be followed by another digit)");
1217             }
1218 41         52 $n .= $ch;
1219 41         51 next_chr;
1220             }
1221              
1222 806   100     2339 while(defined $ch and $ch =~ /\d/){
1223 971         1177 $n .= $ch;
1224 971         1106 next_chr;
1225             }
1226              
1227 806 100 100     1925 if(defined $ch and $ch eq '.'){
1228 49         61 $n .= '.';
1229 49         59 $is_dec = 1;
1230              
1231 49         78 next_chr;
1232 49 100 66     162 if (!defined $ch or $ch !~ /\d/) {
1233 1         3 decode_error("malformed number (no digits after decimal point)");
1234             }
1235             else {
1236 48         94 $n .= $ch;
1237             }
1238              
1239 48   100     63 while(defined(next_chr) and $ch =~ /\d/){
1240 97         152 $n .= $ch;
1241             }
1242             }
1243              
1244 805 100 100     2241 if(defined $ch and ($ch eq 'e' or $ch eq 'E')){
      100        
1245 58         65 $n .= $ch;
1246 58         146 $is_exp = 1;
1247 58         125 next_chr;
1248              
1249 58 100 100     220 if(defined($ch) and ($ch eq '+' or $ch eq '-')){
    100 100        
      100        
1250 38         51 $n .= $ch;
1251 38         103 next_chr;
1252 38 100 66     110 if (!defined $ch or $ch =~ /\D/) {
1253 2         6 decode_error("malformed number (no digits after exp sign)");
1254             }
1255 36         43 $n .= $ch;
1256             }
1257             elsif(defined($ch) and $ch =~ /\d/){
1258 18         27 $n .= $ch;
1259             }
1260             else {
1261 2         11 decode_error("malformed number (no digits after exp sign)");
1262             }
1263              
1264 54   100     68 while(defined(next_chr) and $ch =~ /\d/){
1265 33         44 $n .= $ch;
1266             }
1267              
1268             }
1269              
1270 801         949 $v .= $n;
1271              
1272 801 100 100     1592 if ($is_dec or $is_exp) {
1273 70 100       107 if ($allow_bignum) {
1274 1         868 require Math::BigFloat;
1275 1         21795 return Math::BigFloat->new($v);
1276             }
1277             } else {
1278 731 100       1054 if (length $v > $max_intsize) {
1279 1 50       3 if ($allow_bignum) { # from Adam Sussman
1280 1         5 require Math::BigInt;
1281 1         5 return Math::BigInt->new($v);
1282             }
1283             else {
1284 0         0 return "$v";
1285             }
1286             }
1287             }
1288              
1289 799 100       2002 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   172338 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 5601459 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         3542063 my $limit = $max_unicode_length;
1312 3440100 100       4580104 $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         4401776 while ($limit > 0) { # Until we succeed or exhaust the input
1318 4679197         5028556 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       7189207 if (utf8::decode($copy)) {
1323              
1324             # Is valid: get the first character, convert back to bytes,
1325             # and return those bytes.
1326 3440095         5852801 $copy = substr($copy, 0, 1);
1327 3440095         5307535 utf8::encode($copy);
1328 3440095         3265755 $utf8_len = length $copy;
1329 3440095         6711187 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         1675970 $limit--;
1336             }
1337              
1338             # Failed to find a legal UTF-8 character.
1339 5         9 $utf8_len = 0;
1340 5         39 return;
1341             }
1342              
1343              
1344             sub decode_error {
1345 101     101 0 178 my $error = shift;
1346 101         208 my $no_rep = shift;
1347 101 100       215 my $str = defined $text ? substr($text, $at) : '';
1348 101         140 my $mess = '';
1349 101         127 my $type = 'U*';
1350              
1351 101         162 if ( OLD_PERL ) {
1352             my $type = $] < 5.006 ? 'C*'
1353             : utf8::is_utf8( $str ) ? 'U*' # 5.6
1354             : 'C*'
1355             ;
1356             }
1357              
1358 101         409 for my $c ( unpack( $type, $str ) ) { # emulate pv_uni_display() ?
1359 459         608 my $chr_c = chr($c);
1360 459 50       1109 $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       801 if ( length $mess >= 20 ) {
1370 10         16 $mess .= '...';
1371 10         14 last;
1372             }
1373             }
1374              
1375 101 100       225 unless ( length $mess ) {
1376 30         40 $mess = '(end of string)';
1377             }
1378              
1379             Carp::croak (
1380 101 100       26510 $no_rep ? "$error" : "$error, at character offset $at (before \"$mess\")"
1381             );
1382              
1383             }
1384              
1385              
1386             sub _json_object_hook {
1387 9     9   24 my $o = $_[0];
1388 9         11 my @ks = keys %{$o};
  9         26  
1389              
1390 9 100 66     47 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         9 my @val = $cb_sk_object->{ $ks[0] }->( $o->{$ks[0]} );
1392 4 100       15 if (@val == 0) {
    50          
1393 1         3 return $o;
1394             }
1395             elsif (@val == 1) {
1396 3         11 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       12 my @val = $cb_object->($o) if ($cb_object);
1404 5 100       17 if (@val == 0) {
    50          
1405 3         8 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   1694360 my $uni = 0x10000 + (hex($_[0]) - 0xD800) * 0x400 + (hex($_[1]) - 0xDC00);
1433 1127736         1860742 my $un = pack('U*', $uni);
1434 1127736         1731851 utf8::encode( $un );
1435 1127736         1961670 return $un;
1436             }
1437              
1438              
1439             sub _decode_unicode {
1440 2893171     2893171   4516675 my $un = pack('U', hex shift);
1441 2893171         4446938 utf8::encode( $un );
1442 2893171         6347229 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   381 unless ( defined &utf8::is_utf8 ) {
1452 0         0 require Encode;
1453 0         0 *utf8::is_utf8 = *Encode::is_utf8;
1454             }
1455              
1456 57         118 if ( !OLD_PERL ) {
1457 57         188 *JSON::PP::JSON_PP_encode_ascii = \&_encode_ascii;
1458 57         117 *JSON::PP::JSON_PP_encode_latin1 = \&_encode_latin1;
1459 57         117 *JSON::PP::JSON_PP_decode_surrogates = \&_decode_surrogates;
1460 57         184 *JSON::PP::JSON_PP_decode_unicode = \&_decode_unicode;
1461              
1462 57 50       228 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 51647 local $Carp::CarpLevel = 1;
1482 744   66     1908 ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_parse( @_ );
1483             }
1484              
1485              
1486             sub JSON::PP::incr_skip {
1487 2   33 2 1 1703 ( $_[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 21577 eval q{
  304 50       46339  
  304         577  
  0         0  
  304         1397  
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   3140 eval 'require Scalar::Util';
1515 57 50       1626 unless($@){
1516 57         223 *JSON::PP::blessed = \&Scalar::Util::blessed;
1517 57         106 *JSON::PP::reftype = \&Scalar::Util::reftype;
1518 57         5272 *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 1023 if (blessed $_[0]) {
1577             return (
1578 2   33     26 $_[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   5567 BEGIN { CORE_BOOL and warnings->unimport('experimental::builtin') }
1585             return builtin::is_bool($_[0]);
1586             }
1587 3         11 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   381 use strict;
  57         105  
  57         1501  
1600              
1601 57     57   263 use constant INCR_M_WS => 0; # initial whitespace skipping
  57         102  
  57         3047  
1602 57     57   325 use constant INCR_M_STR => 1; # inside string
  57         119  
  57         2454  
1603 57     57   306 use constant INCR_M_BS => 2; # inside backslash
  57         84  
  57         2429  
1604 57     57   285 use constant INCR_M_JSON => 3; # outside anything, count nesting
  57         99  
  57         2371  
1605 57     57   285 use constant INCR_M_C0 => 4;
  57         78  
  57         2336  
1606 57     57   267 use constant INCR_M_C1 => 5;
  57         99  
  57         2170  
1607 57     57   297 use constant INCR_M_TFN => 6;
  57         100  
  57         2271  
1608 57     57   298 use constant INCR_M_NUM => 7;
  57         102  
  57         14709  
1609              
1610             $JSON::backportPP::IncrParser::VERSION = '1.01';
1611              
1612             sub new {
1613 57     57   90 my ( $class ) = @_;
1614              
1615 57         304 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   1105 my ( $self, $coder, $text ) = @_;
1626              
1627 744 100       1145 $self->{incr_text} = '' unless ( defined $self->{incr_text} );
1628              
1629 744 100       1118 if ( defined $text ) {
1630 402         886 $self->{incr_text} .= $text;
1631             }
1632              
1633 744 100       1648 if ( defined wantarray ) {
1634 383         634 my $max_size = $coder->get_max_size;
1635 383         485 my $p = $self->{incr_pos};
1636 383         427 my @ret;
1637             {
1638 383         398 do {
  383         385  
1639 394 100 100     1158 unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) {
1640 393         836 $self->_incr_parse( $coder );
1641              
1642 392 100 100     719 if ( $max_size and $self->{incr_pos} > $max_size ) {
1643 1         72 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     1047 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     237 if ( $self->{incr_mode} == INCR_M_WS and $self->{incr_pos} ) {
1648 7         7 $self->{incr_pos} = 0;
1649 7         10 $self->{incr_text} = '';
1650             }
1651 83         129 last;
1652             }
1653             }
1654              
1655 309 100       6081 unless ( $coder->get_utf8 ) {
1656 301         804 utf8::decode( $self->{incr_text} );
1657             }
1658              
1659 309         699 my ($obj, $offset) = $coder->PP_decode_json( $self->{incr_text}, 0x00000001 );
1660 298         481 push @ret, $obj;
1661 57     57   368 use bytes;
  57         85  
  57         222  
1662 298   50     705 $self->{incr_text} = substr( $self->{incr_text}, $offset || 0 );
1663 298         389 $self->{incr_pos} = 0;
1664 298         346 $self->{incr_nest} = 0;
1665 298         321 $self->{incr_mode} = 0;
1666 298 100       519 last unless wantarray;
1667             } while ( wantarray );
1668             }
1669              
1670 370 100       539 if ( wantarray ) {
1671 7         38 return @ret;
1672             }
1673             else { # in scalar context
1674 363 100       1138 return defined $ret[0] ? $ret[0] : undef;
1675             }
1676             }
1677             }
1678              
1679              
1680             sub _incr_parse {
1681 393     393   537 my ($self, $coder) = @_;
1682 393         844 my $text = $self->{incr_text};
1683 393         453 my $len = length $text;
1684 393         441 my $p = $self->{incr_pos};
1685              
1686             INCR_PARSE:
1687 393         633 while ( $len > $p ) {
1688 3084         3533 my $s = substr( $text, $p, 1 );
1689 3084 50       3739 last INCR_PARSE unless defined $s;
1690 3084         2905 my $mode = $self->{incr_mode};
1691              
1692 3084 100 100     9265 if ( $mode == INCR_M_WS ) {
    50          
    100          
    100          
    100          
    100          
    50          
1693 335         475 while ( $len > $p ) {
1694 594         679 $s = substr( $text, $p, 1 );
1695 594 50       779 last INCR_PARSE unless defined $s;
1696 594 100       843 if ( ord($s) > ord " " ) {
1697 328 100       509 if ( $s eq '#' ) {
1698 6         6 $self->{incr_mode} = INCR_M_C0;
1699 6         9 redo INCR_PARSE;
1700             } else {
1701 322         340 $self->{incr_mode} = INCR_M_JSON;
1702 322         530 redo INCR_PARSE;
1703             }
1704             }
1705 266         375 $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         14 while ( $len > $p ) {
1713 45         38 $s = substr( $text, $p, 1 );
1714 45 50       53 last INCR_PARSE unless defined $s;
1715 45 100       51 if ( $s eq "\n" ) {
1716 9 100       12 $self->{incr_mode} = $self->{incr_mode} == INCR_M_C0 ? INCR_M_WS : INCR_M_JSON;
1717 9         6 last;
1718             }
1719 36         36 $p++;
1720             }
1721 9         15 next;
1722             } elsif ( $mode == INCR_M_TFN ) {
1723 36 50 66     65 last INCR_PARSE if $p >= $len && $self->{incr_nest};
1724 35         70 while ( $len > $p ) {
1725 140         182 $s = substr( $text, $p++, 1 );
1726 140 100 66     383 next if defined $s and $s =~ /[rueals]/;
1727 35         58 last;
1728             }
1729 35         41 $p--;
1730 35         48 $self->{incr_mode} = INCR_M_JSON;
1731              
1732 35 50       44 last INCR_PARSE unless $self->{incr_nest};
1733 35         36 redo INCR_PARSE;
1734             } elsif ( $mode == INCR_M_NUM ) {
1735 399 100 100     581 last INCR_PARSE if $p >= $len && $self->{incr_nest};
1736 396         505 while ( $len > $p ) {
1737 482         562 $s = substr( $text, $p++, 1 );
1738 482 100 66     1163 next if defined $s and $s =~ /[0-9eE.+\-]/;
1739 389         395 last;
1740             }
1741 396         347 $p--;
1742 396         403 $self->{incr_mode} = INCR_M_JSON;
1743              
1744 396 100       546 last INCR_PARSE unless $self->{incr_nest};
1745 378         391 redo INCR_PARSE;
1746             } elsif ( $mode == INCR_M_STR ) {
1747 805         1052 while ( $len > $p ) {
1748 84413         86544 $s = substr( $text, $p, 1 );
1749 84413 50       101389 last INCR_PARSE unless defined $s;
1750 84413 100       119510 if ( $s eq '"' ) {
    100          
1751 780         785 $p++;
1752 780         928 $self->{incr_mode} = INCR_M_JSON;
1753              
1754 780 100       1040 last INCR_PARSE unless $self->{incr_nest};
1755 760         932 redo INCR_PARSE;
1756             }
1757             elsif ( $s eq '\\' ) {
1758 508         494 $p++;
1759 508 50       695 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         101897 $p++;
1765             }
1766             } elsif ( $mode == INCR_M_JSON ) {
1767 1500         1894 while ( $len > $p ) {
1768 3614         4090 $s = substr( $text, $p++, 1 );
1769 3614 50 66     16435 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       980 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         882 next;
1778             } elsif ( $s eq 't' or $s eq 'f' or $s eq 'n' ) {
1779 36         47 $self->{incr_mode} = INCR_M_TFN;
1780 36         41 redo INCR_PARSE;
1781             } elsif ( $s =~ /^[0-9\-]$/ ) {
1782 398         462 $self->{incr_mode} = INCR_M_NUM;
1783 398         430 redo INCR_PARSE;
1784             } elsif ( $s eq '"' ) {
1785 783         950 $self->{incr_mode} = INCR_M_STR;
1786 783         884 redo INCR_PARSE;
1787             } elsif ( $s eq '[' or $s eq '{' ) {
1788 383 100       727 if ( ++$self->{incr_nest} > $coder->get_max_depth ) {
1789 1         154 Carp::croak('json text or perl structure exceeds maximum nesting level (max_depth set too low?)');
1790             }
1791 382         576 next;
1792             } elsif ( $s eq ']' or $s eq '}' ) {
1793 369 100       598 if ( --$self->{incr_nest} <= 0 ) {
1794 270         365 last INCR_PARSE;
1795             }
1796             } elsif ( $s eq '#' ) {
1797 3         4 $self->{incr_mode} = INCR_M_C1;
1798 3         3 redo INCR_PARSE;
1799             }
1800             }
1801             }
1802             }
1803              
1804 392         452 $self->{incr_pos} = $p;
1805 392 100       706 $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         7 $self->{incr_text} = substr( $self->{incr_text}, $self->{incr_pos} );
1820 2         4 $self->{incr_pos} = 0;
1821 2         2 $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__