File Coverage

blib/lib/JSON/PP.pm
Criterion Covered Total %
statement 849 992 85.5
branch 473 646 73.2
condition 182 266 68.4
subroutine 133 168 79.1
pod 46 96 47.9
total 1683 2168 77.6


line stmt bran cond sub pod time code
1             package JSON::PP;
2              
3             # JSON-2.0
4              
5 64     64   4142811 use 5.005;
  64         676  
6 64     64   364 use strict;
  64         127  
  64         1424  
7              
8 64     64   358 use Exporter ();
  64         156  
  64         2166  
9 64     64   2540 BEGIN { @JSON::PP::ISA = ('Exporter') }
10              
11 64     64   59258 use overload ();
  64         49834  
  64         1638  
12 64     64   25276 use JSON::PP::Boolean;
  64         174  
  64         1838  
13              
14 64     64   405 use Carp ();
  64         134  
  64         3162  
15             #use Devel::Peek;
16              
17             $JSON::PP::VERSION = '4.15';
18              
19             @JSON::PP::EXPORT = qw(encode_json decode_json from_json to_json);
20              
21             # instead of hash-access, i tried index-access for speed.
22             # but this method is not faster than what i expected. so it will be changed.
23              
24 64     64   408 use constant P_ASCII => 0;
  64         135  
  64         6745  
25 64     64   491 use constant P_LATIN1 => 1;
  64         175  
  64         3666  
26 64     64   382 use constant P_UTF8 => 2;
  64         156  
  64         3530  
27 64     64   829 use constant P_INDENT => 3;
  64         191  
  64         3326  
28 64     64   374 use constant P_CANONICAL => 4;
  64         123  
  64         3130  
29 64     64   365 use constant P_SPACE_BEFORE => 5;
  64         146  
  64         3344  
30 64     64   392 use constant P_SPACE_AFTER => 6;
  64         150  
  64         3461  
31 64     64   404 use constant P_ALLOW_NONREF => 7;
  64         145  
  64         2988  
32 64     64   367 use constant P_SHRINK => 8;
  64         123  
  64         3218  
33 64     64   398 use constant P_ALLOW_BLESSED => 9;
  64         171  
  64         4763  
34 64     64   424 use constant P_CONVERT_BLESSED => 10;
  64         123  
  64         3479  
35 64     64   381 use constant P_RELAXED => 11;
  64         109  
  64         3215  
36              
37 64     64   374 use constant P_LOOSE => 12;
  64         1292  
  64         3034  
38 64     64   381 use constant P_ALLOW_BIGNUM => 13;
  64         121  
  64         2972  
39 64     64   368 use constant P_ALLOW_BAREKEY => 14;
  64         119  
  64         3266  
40 64     64   374 use constant P_ALLOW_SINGLEQUOTE => 15;
  64         123  
  64         3018  
41 64     64   369 use constant P_ESCAPE_SLASH => 16;
  64         114  
  64         2968  
42 64     64   369 use constant P_AS_NONBLESSED => 17;
  64         200  
  64         3341  
43              
44 64     64   388 use constant P_ALLOW_UNKNOWN => 18;
  64         152  
  64         3124  
45 64     64   392 use constant P_ALLOW_TAGS => 19;
  64         129  
  64         4071  
46              
47 64 50   64   408 use constant OLD_PERL => $] < 5.008 ? 1 : 0;
  64         117  
  64         4299  
48 64   50 64   419 use constant USE_B => $ENV{PERL_JSON_PP_USE_B} || 0;
  64         165  
  64         4779  
49 64     64   436 use constant CORE_BOOL => defined &builtin::is_bool;
  64         143  
  64         8467  
50              
51             my $invalid_char_re;
52              
53             BEGIN {
54 64     64   254 $invalid_char_re = "[";
55 64         184 for my $i (0 .. 0x01F, 0x22, 0x5c) { # '/' is ok
56 2176         3343 $invalid_char_re .= quotemeta chr utf8::unicode_to_native($i);
57             }
58              
59 64         3556 $invalid_char_re = qr/$invalid_char_re]/;
60             }
61              
62             BEGIN {
63 64     64   10638 if (USE_B) {
64             require B;
65             }
66             }
67              
68             BEGIN {
69 64     64   472 my @xs_compati_bit_properties = qw(
70             latin1 ascii utf8 indent canonical space_before space_after allow_nonref shrink
71             allow_blessed convert_blessed relaxed allow_unknown
72             allow_tags
73             );
74 64         193 my @pp_bit_properties = qw(
75             allow_singlequote allow_bignum loose
76             allow_barekey escape_slash as_nonblessed
77             );
78              
79             # Perl version check, Unicode handling is enabled?
80             # Helper module sets @JSON::PP::_properties.
81 64         139 if ( OLD_PERL ) {
82             my $helper = $] >= 5.006 ? 'JSON::PP::Compat5006' : 'JSON::PP::Compat5005';
83             eval qq| require $helper |;
84             if ($@) { Carp::croak $@; }
85             }
86              
87 64         220 for my $name (@xs_compati_bit_properties, @pp_bit_properties) {
88 1280         5117 my $property_id = 'P_' . uc($name);
89              
90 1280 50   2 1 194966 eval qq/
  2 50   1 1 530  
  2 50   2 1 6  
  2 50   24653 1 7  
  0 50   1 1 0  
  2 50   1 1 6  
  1 100   3 1 5  
  1 100   0 0 4  
  1 50   12292 1 3  
  0 50   10 1 0  
  1 50   4 1 3  
  2 50   1 1 479  
  2 100   0 0 8  
  2 100   0 0 6  
  0 0   0 0 0  
  2 0   0 0 4  
  24653 100   0 0 97801  
  24653 50   0 0 51635  
  9286 100   0 0 21881  
  15367 50   0 0 31364  
  24653 50   0 0 404870  
  1 50   0 0 577  
  1 50   0 0 3  
  1 50   0 0 4  
  0 0   0 0 0  
  1 0   0 0 3  
  1 0   0 0 5  
  1 0   0 0 3  
  1 0   0 0 3  
  0 0   0 0 0  
  1 0   0 0 30  
  3 0   309 0 847  
  3 0   6 1 9  
  2 0   2 1 5  
  1 0   0 1 3  
  3 0   14 1 12  
  0 0   21504 1 0  
  0 0   7 1 0  
  0 0   6 1 0  
  0 0   18466 1 0  
  0 0       0  
  12292 0       37821  
  12292 0       26060  
  12292 100       25005  
  0 50       0  
  12292 100       86650  
  10 50       202  
  10 50       24  
  10 0       35  
  0 0       0  
  10 50       23  
  4 50       34  
  4 50       15  
  4 50       22  
  0 50       0  
  4 100       47  
  1 50       6  
  1 100       4  
  1 100       3  
  0 50       0  
  1         4  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  309         1379  
  6         670  
  6         15  
  4         9  
  2         6  
  6         88  
  2         14  
  2         6  
  2         47  
  0         0  
  2         43  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  14         48  
  14         29  
  14         47  
  0         0  
  14         29  
  21504         65175  
  21504         42239  
  21504         51695  
  0         0  
  21504         80002  
  7         25  
  7         15  
  4         7  
  3         7  
  7         15  
  6         19  
  6         14  
  4         9  
  2         5  
  6         81  
  18466         56426  
  18466         36265  
  18466         36164  
  0         0  
  18466         273909  
91             sub $name {
92             my \$enable = defined \$_[1] ? \$_[1] : 1;
93              
94             if (\$enable) {
95             \$_[0]->{PROPS}->[$property_id] = 1;
96             }
97             else {
98             \$_[0]->{PROPS}->[$property_id] = 0;
99             }
100              
101             \$_[0];
102             }
103              
104             sub get_$name {
105             \$_[0]->{PROPS}->[$property_id] ? 1 : '';
106             }
107             /;
108             }
109              
110             }
111              
112              
113              
114             # Functions
115              
116             my $JSON; # cache
117              
118             sub encode_json ($) { # encode
119 186   66 186 1 1226 ($JSON ||= __PACKAGE__->new->utf8)->encode(@_);
120             }
121              
122              
123             sub decode_json { # decode
124 6206   66 6206 1 76764 ($JSON ||= __PACKAGE__->new->utf8)->decode(@_);
125             }
126              
127             # Obsoleted
128              
129             sub to_json($) {
130 0     0 0 0 Carp::croak ("JSON::PP::to_json has been renamed to encode_json.");
131             }
132              
133              
134             sub from_json($) {
135 0     0 0 0 Carp::croak ("JSON::PP::from_json has been renamed to decode_json.");
136             }
137              
138              
139             # Methods
140              
141             sub new {
142 43174     43174 1 2018400 my $class = shift;
143 43174         130654 my $self = {
144             max_depth => 512,
145             max_size => 0,
146             indent_length => 3,
147             };
148              
149 43174         108605 $self->{PROPS}[P_ALLOW_NONREF] = 1;
150              
151 43174         1038037 bless $self, $class;
152             }
153              
154              
155             sub encode {
156 25141     25141 1 145045 return $_[0]->PP_encode_json($_[1]);
157             }
158              
159              
160             sub decode {
161 24952     24952 1 124542 return $_[0]->PP_decode_json($_[1], 0x00000000);
162             }
163              
164              
165             sub decode_prefix {
166 8     8 1 859 return $_[0]->PP_decode_json($_[1], 0x00000001);
167             }
168              
169              
170             # accessor
171              
172              
173             # pretty printing
174              
175             sub pretty {
176 5     5 1 3160 my ($self, $v) = @_;
177 5 50       14 my $enable = defined $v ? $v : 1;
178              
179 5 100       12 if ($enable) { # indent_length(3) for JSON::XS compatibility
180 3         68 $self->indent(1)->space_before(1)->space_after(1);
181             }
182             else {
183 2         48 $self->indent(0)->space_before(0)->space_after(0);
184             }
185              
186 5         10 $self;
187             }
188              
189             # etc
190              
191             sub max_depth {
192 5 50   5 1 1406 my $max = defined $_[1] ? $_[1] : 0x80000000;
193 5         11 $_[0]->{max_depth} = $max;
194 5         34 $_[0];
195             }
196              
197              
198 383     383 0 818 sub get_max_depth { $_[0]->{max_depth}; }
199              
200              
201             sub max_size {
202 3 50   3 1 462 my $max = defined $_[1] ? $_[1] : 0;
203 3         10 $_[0]->{max_size} = $max;
204 3         12 $_[0];
205             }
206              
207              
208 383     383 0 673 sub get_max_size { $_[0]->{max_size}; }
209              
210             sub boolean_values {
211 6     6 1 1862 my $self = shift;
212 6 100       19 if (@_) {
213 4         10 my ($false, $true) = @_;
214 4         11 $self->{false} = $false;
215 4         9 $self->{true} = $true;
216 4         7 if (CORE_BOOL) {
217 64     64   124722 BEGIN { CORE_BOOL and warnings->unimport(qw(experimental::builtin)) }
218             if (builtin::is_bool($true) && builtin::is_bool($false) && $true && !$false) {
219             $self->{core_bools} = !!1;
220             }
221             else {
222             delete $self->{core_bools};
223             }
224             }
225             } else {
226 2         4 delete $self->{false};
227 2         4 delete $self->{true};
228 2         3 delete $self->{core_bools};
229             }
230 6         12 return $self;
231             }
232              
233             sub core_bools {
234 1     1 1 2 my $self = shift;
235 1 50       5 my $core_bools = defined $_[0] ? $_[0] : 1;
236 1 50       4 if ($core_bools) {
237 1         3 $self->{true} = !!1;
238 1         2 $self->{false} = !!0;
239 1         2 $self->{core_bools} = !!1;
240             }
241             else {
242 0         0 $self->{true} = $JSON::PP::true;
243 0         0 $self->{false} = $JSON::PP::false;
244 0         0 $self->{core_bools} = !!0;
245             }
246 1         3 return $self;
247             }
248              
249             sub get_core_bools {
250 3     3 0 13 my $self = shift;
251 3         21 return !!$self->{core_bools};
252             }
253              
254             sub unblessed_bool {
255 0     0 0 0 my $self = shift;
256 0         0 return $self->core_bools(@_);
257             }
258              
259             sub get_unblessed_bool {
260 0     0 0 0 my $self = shift;
261 0         0 return $self->get_core_bools(@_);
262             }
263              
264             sub get_boolean_values {
265 5     5 0 2736 my $self = shift;
266 5 50 66     27 if (exists $self->{true} and exists $self->{false}) {
267 3         29 return @$self{qw/false true/};
268             }
269 2         8 return;
270             }
271              
272             sub filter_json_object {
273 3 100 66 3 1 16 if (defined $_[1] and ref $_[1] eq 'CODE') {
274 2         5 $_[0]->{cb_object} = $_[1];
275             } else {
276 1         3 delete $_[0]->{cb_object};
277             }
278 3 50 66     24 $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0;
279 3         6 $_[0];
280             }
281              
282             sub filter_json_single_key_object {
283 4 50 33 4 1 19 if (@_ == 1 or @_ > 3) {
284 0         0 Carp::croak("Usage: JSON::PP::filter_json_single_key_object(self, key, callback = undef)");
285             }
286 4 100 66     17 if (defined $_[2] and ref $_[2] eq 'CODE') {
287 3         9 $_[0]->{cb_sk_object}->{$_[1]} = $_[2];
288             } else {
289 1         6 delete $_[0]->{cb_sk_object}->{$_[1]};
290 1 50       2 delete $_[0]->{cb_sk_object} unless %{$_[0]->{cb_sk_object} || {}};
  1 50       6  
291             }
292 4 50 33     14 $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0;
293 4         7 $_[0];
294             }
295              
296             sub indent_length {
297 0 0 0 0 1 0 if (!defined $_[1] or $_[1] > 15 or $_[1] < 0) {
      0        
298 0         0 Carp::carp "The acceptable range of indent_length() is 0 to 15.";
299             }
300             else {
301 0         0 $_[0]->{indent_length} = $_[1];
302             }
303 0         0 $_[0];
304             }
305              
306             sub get_indent_length {
307 0     0 0 0 $_[0]->{indent_length};
308             }
309              
310             sub sort_by {
311 3 50   3 1 1879 $_[0]->{sort_by} = defined $_[1] ? $_[1] : 1;
312 3         11 $_[0];
313             }
314              
315             sub allow_bigint {
316 0     0 0 0 Carp::carp("allow_bigint() is obsoleted. use allow_bignum() instead.");
317 0         0 $_[0]->allow_bignum;
318             }
319              
320             ###############################
321              
322             ###
323             ### Perl => JSON
324             ###
325              
326              
327             { # Convert
328              
329             my $max_depth;
330             my $indent;
331             my $ascii;
332             my $latin1;
333             my $utf8;
334             my $space_before;
335             my $space_after;
336             my $canonical;
337             my $allow_blessed;
338             my $convert_blessed;
339              
340             my $indent_length;
341             my $escape_slash;
342             my $bignum;
343             my $as_nonblessed;
344             my $allow_tags;
345              
346             my $depth;
347             my $indent_count;
348             my $keysort;
349              
350              
351             sub PP_encode_json {
352 25141     25141 0 37748 my $self = shift;
353 25141         35665 my $obj = shift;
354              
355 25141         35547 $indent_count = 0;
356 25141         33572 $depth = 0;
357              
358 25141         38297 my $props = $self->{PROPS};
359              
360             ($ascii, $latin1, $utf8, $indent, $canonical, $space_before, $space_after, $allow_blessed,
361             $convert_blessed, $escape_slash, $bignum, $as_nonblessed, $allow_tags)
362 25141         46503 = @{$props}[P_ASCII .. P_SPACE_AFTER, P_ALLOW_BLESSED, P_CONVERT_BLESSED,
  25141         84703  
363             P_ESCAPE_SLASH, P_ALLOW_BIGNUM, P_AS_NONBLESSED, P_ALLOW_TAGS];
364              
365 25141         40834 ($max_depth, $indent_length) = @{$self}{qw/max_depth indent_length/};
  25141         49737  
366              
367 25141 100   588   52537 $keysort = $canonical ? sub { $a cmp $b } : undef;
  588         1211  
368              
369 25141 100       60633 if ($self->{sort_by}) {
370             $keysort = ref($self->{sort_by}) eq 'CODE' ? $self->{sort_by}
371             : $self->{sort_by} =~ /\D+/ ? $self->{sort_by}
372 3 100   20   19 : sub { $a cmp $b };
  20 100       30  
373             }
374              
375 25141 50 66     65629 encode_error("hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)")
376             if(!ref $obj and !$props->[ P_ALLOW_NONREF ]);
377              
378 25141         60677 my $str = $self->object_to_json($obj);
379              
380 25123 100       57415 $str .= "\n" if ( $indent ); # JSON::XS 2.26 compatible
381              
382 25123         81306 return $str;
383             }
384              
385              
386             sub object_to_json {
387 25491     25491 0 46492 my ($self, $obj) = @_;
388 25491         43358 my $type = ref($obj);
389              
390 25491 100       67110 if($type eq 'HASH'){
    100          
    100          
391 346         704 return $self->hash_to_json($obj);
392             }
393             elsif($type eq 'ARRAY'){
394 25010         59217 return $self->array_to_json($obj);
395             }
396             elsif ($type) { # blessed object?
397 54 100       191 if (blessed($obj)) {
398              
399 34 100       217 return $self->value_to_json($obj) if ( $obj->isa('JSON::PP::Boolean') );
400              
401 14 100 100     65 if ( $allow_tags and $obj->can('FREEZE') ) {
402 1   33     6 my $obj_class = ref $obj || $obj;
403 1         4 $obj = bless $obj, $obj_class;
404 1         3 my @results = $obj->FREEZE('JSON');
405 1 50 33     1042 if ( @results and ref $results[0] ) {
406 0 0       0 if ( refaddr( $obj ) eq refaddr( $results[0] ) ) {
407 0         0 encode_error( sprintf(
408             "%s::FREEZE method returned same object as was passed instead of a new one",
409             ref $obj
410             ) );
411             }
412             }
413 1         9 return '("'.$obj_class.'")['.join(',', @results).']';
414             }
415              
416 13 100 100     105 if ( $convert_blessed and $obj->can('TO_JSON') ) {
417 5         19 my $result = $obj->TO_JSON();
418 5 100 66     845 if ( defined $result and ref( $result ) ) {
419 2 100       17 if ( refaddr( $obj ) eq refaddr( $result ) ) {
420 1         8 encode_error( sprintf(
421             "%s::TO_JSON method returned same object as was passed instead of a new one",
422             ref $obj
423             ) );
424             }
425             }
426              
427 4         25 return $self->object_to_json( $result );
428             }
429              
430 8 100 66     23 return "$obj" if ( $bignum and _is_bignum($obj) );
431              
432 5 100       11 if ($allow_blessed) {
433 3 50       7 return $self->blessed_to_json($obj) if ($as_nonblessed); # will be removed.
434 3         8 return 'null';
435             }
436 2         15 encode_error( sprintf("encountered object '%s', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled (or TO_JSON/FREEZE method missing)", $obj)
437             );
438             }
439             else {
440 20         57 return $self->value_to_json($obj);
441             }
442             }
443             else{
444 81         171 return $self->value_to_json($obj);
445             }
446             }
447              
448              
449             sub hash_to_json {
450 346     346 0 547 my ($self, $obj) = @_;
451 346         481 my @res;
452              
453 346 100       677 encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)")
454             if (++$depth > $max_depth);
455              
456 345 100       765 my ($pre, $post) = $indent ? $self->_up_indent() : ('', '');
457 345 100       869 my $del = ($space_before ? ' ' : '') . ':' . ($space_after ? ' ' : '');
    100          
458              
459 345         634 for my $k ( _sort( $obj ) ) {
460 744         1014 if ( OLD_PERL ) { utf8::decode($k) } # key for Perl 5.6 / be optimized
461             push @res, $self->string_to_json( $k )
462             . $del
463 744 100       1363 . ( ref $obj->{$k} ? $self->object_to_json( $obj->{$k} ) : $self->value_to_json( $obj->{$k} ) );
464             }
465              
466 343         637 --$depth;
467 343 100       580 $self->_down_indent() if ($indent);
468              
469 343 100       685 return '{}' unless @res;
470 333         1593 return '{' . $pre . join( ",$pre", @res ) . $post . '}';
471             }
472              
473              
474             sub array_to_json {
475 25010     25010 0 42588 my ($self, $obj) = @_;
476 25010         37300 my @res;
477              
478 25010 100       52979 encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)")
479             if (++$depth > $max_depth);
480              
481 25009 100       57150 my ($pre, $post) = $indent ? $self->_up_indent() : ('', '');
482              
483 25009         48551 for my $v (@$obj){
484 25795 100       72263 push @res, ref($v) ? $self->object_to_json($v) : $self->value_to_json($v);
485             }
486              
487 24995         41621 --$depth;
488 24995 100       47457 $self->_down_indent() if ($indent);
489              
490 24995 100       53275 return '[]' unless @res;
491 24985         197275 return '[' . $pre . join( ",$pre", @res ) . $post . ']';
492             }
493              
494             sub _looks_like_number {
495 26230     26230   38372 my $value = shift;
496 26230         35274 if (USE_B) {
497             my $b_obj = B::svref_2object(\$value);
498             my $flags = $b_obj->FLAGS;
499             return 1 if $flags & ( B::SVp_IOK() | B::SVp_NOK() ) and !( $flags & B::SVp_POK() );
500             return;
501             } else {
502 64     64   568 no warnings 'numeric';
  64         167  
  64         10557  
503             # if the utf8 flag is on, it almost certainly started as a string
504 26230 100       83919 return if utf8::is_utf8($value);
505             # detect numbers
506             # string & "" -> ""
507             # number & "" -> 0 (with warning)
508             # nan and inf can detect as numbers, so check with * 0
509 13743 100       58682 return unless length((my $dummy = "") & $value);
510 817 100       1856 return unless 0 + $value eq $value;
511 816 50       2391 return 1 if $value * 0 == 0;
512 0         0 return -1; # inf/nan
513             }
514             }
515              
516             sub value_to_json {
517 26314     26314 0 46708 my ($self, $value) = @_;
518              
519 26314 100       52998 return 'null' if(!defined $value);
520              
521 26270         40184 my $type = ref($value);
522              
523 26270 100 66     46568 if (!$type) {
    100          
524 64     64   73108 BEGIN { CORE_BOOL and warnings->unimport('experimental::builtin') }
525 26230 100       48456 if (CORE_BOOL && builtin::is_bool($value)) {
526             return $value ? 'true' : 'false';
527             }
528 0         0 elsif (_looks_like_number($value)) {
529 816         2205 return $value;
530             }
531 25414         65006 return $self->string_to_json($value);
532             }
533             elsif( blessed($value) and $value->isa('JSON::PP::Boolean') ){
534 20 100       137 return $$value == 1 ? 'true' : 'false';
535             }
536             else {
537 20 50       63 if ((overload::StrVal($value) =~ /=(\w+)/)[0]) {
538 0         0 return $self->value_to_json("$value");
539             }
540              
541 20 100 100     184 if ($type eq 'SCALAR' and defined $$value) {
542             return $$value eq '1' ? 'true'
543             : $$value eq '0' ? 'false'
544 7 100       67 : $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ? 'null'
    100          
    100          
545             : encode_error("cannot encode reference to scalar");
546             }
547              
548 13 100       34 if ( $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ) {
549 4         13 return 'null';
550             }
551             else {
552 9 100 100     39 if ( $type eq 'SCALAR' or $type eq 'REF' ) {
553 6         15 encode_error("cannot encode reference to scalar");
554             }
555             else {
556 3         33 encode_error("encountered $value, but JSON can only represent references to arrays or hashes");
557             }
558             }
559              
560             }
561             }
562              
563              
564             my %esc = (
565             "\n" => '\n',
566             "\r" => '\r',
567             "\t" => '\t',
568             "\f" => '\f',
569             "\b" => '\b',
570             "\"" => '\"',
571             "\\" => '\\\\',
572             "\'" => '\\\'',
573             );
574              
575              
576             sub string_to_json {
577 26158     26158 0 52521 my ($self, $arg) = @_;
578              
579 26158         487159 $arg =~ s/(["\\\n\r\t\f\b])/$esc{$1}/g;
580 26158 100       64145 $arg =~ s/\//\\\//g if ($escape_slash);
581              
582             # On ASCII platforms, matches [\x00-\x08\x0b\x0e-\x1f]
583 26158         170064 $arg =~ s/([^\n\t\c?[:^cntrl:][:^ascii:]])/'\\u00' . unpack('H2', $1)/eg;
  578676         1597526  
584              
585 26158 100       59792 if ($ascii) {
586 12297         31049 $arg = JSON_PP_encode_ascii($arg);
587             }
588              
589 26158 100       188313 if ($latin1) {
590 2         6 $arg = JSON_PP_encode_latin1($arg);
591             }
592              
593 26158 100       51894 if ($utf8) {
594 12551         54462 utf8::encode($arg);
595             }
596              
597 26158         244268 return '"' . $arg . '"';
598             }
599              
600              
601             sub blessed_to_json {
602 0   0 0 0 0 my $reftype = reftype($_[1]) || '';
603 0 0       0 if ($reftype eq 'HASH') {
    0          
604 0         0 return $_[0]->hash_to_json($_[1]);
605             }
606             elsif ($reftype eq 'ARRAY') {
607 0         0 return $_[0]->array_to_json($_[1]);
608             }
609             else {
610 0         0 return 'null';
611             }
612             }
613              
614              
615             sub encode_error {
616 18     18 0 35 my $error = shift;
617 18         2459 Carp::croak "$error";
618             }
619              
620              
621             sub _sort {
622 345 100   345   606 defined $keysort ? (sort $keysort (keys %{$_[0]})) : keys %{$_[0]};
  222         1148  
  123         496  
623             }
624              
625              
626             sub _up_indent {
627 9     9   13 my $self = shift;
628 9         18 my $space = ' ' x $indent_length;
629              
630 9         17 my ($pre,$post) = ('','');
631              
632 9         17 $post = "\n" . $space x $indent_count;
633              
634 9         11 $indent_count++;
635              
636 9         12 $pre = "\n" . $space x $indent_count;
637              
638 9         22 return ($pre,$post);
639             }
640              
641              
642 9     9   13 sub _down_indent { $indent_count--; }
643              
644              
645             sub PP_encode_box {
646             {
647 0     0 0 0 depth => $depth,
648             indent_count => $indent_count,
649             };
650             }
651              
652             } # Convert
653              
654              
655             sub _encode_ascii {
656             join('',
657             map {
658 12297 100   12297   338543 chr($_) =~ /[[:ascii:]]/ ?
  6259537 100       16273558  
659             chr($_) :
660             $_ <= 65535 ?
661             sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_));
662             } unpack('U*', $_[0])
663             );
664             }
665              
666              
667             sub _encode_latin1 {
668             join('',
669             map {
670 2 50   2   10 $_ <= 255 ?
  22 100       60  
671             chr($_) :
672             $_ <= 65535 ?
673             sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_));
674             } unpack('U*', $_[0])
675             );
676             }
677              
678              
679             sub _encode_surrogates { # from perlunicode
680 1127975     1127975   1420649 my $uni = $_[0] - 0x10000;
681 1127975         3241500 return ($uni / 0x400 + 0xD800, $uni % 0x400 + 0xDC00);
682             }
683              
684              
685             sub _is_bignum {
686 3 100   3   19 $_[0]->isa('Math::BigInt') or $_[0]->isa('Math::BigFloat');
687             }
688              
689              
690              
691             #
692             # JSON => Perl
693             #
694              
695             my $max_intsize;
696              
697             BEGIN {
698 64     64   348 my $checkint = 1111;
699 64         363 for my $d (5..64) {
700 1088         1898 $checkint .= 1;
701 1088         33351 my $int = eval qq| $checkint |;
702 1088 100       5216 if ($int =~ /[eE]/) {
703 64         152 $max_intsize = $d - 1;
704 64         28593 last;
705             }
706             }
707             }
708              
709             { # PARSE
710              
711             my %escapes = ( # by Jeremy Muhlich
712             b => "\b",
713             t => "\t",
714             n => "\n",
715             f => "\f",
716             r => "\r",
717             '\\' => '\\',
718             '"' => '"',
719             '/' => '/',
720             );
721              
722             my $text; # json data
723             my $at; # offset
724             my $ch; # first character
725             my $len; # text length (changed according to UTF8 or NON UTF8)
726             # INTERNAL
727             my $depth; # nest counter
728             my $encoding; # json text encoding
729             my $is_valid_utf8; # temp variable
730             my $utf8_len; # utf8 byte length
731             # FLAGS
732             my $utf8; # must be utf8
733             my $max_depth; # max nest number of objects and arrays
734             my $max_size;
735             my $relaxed;
736             my $cb_object;
737             my $cb_sk_object;
738              
739             my $F_HOOK;
740              
741             my $allow_bignum; # using Math::BigInt/BigFloat
742             my $singlequote; # loosely quoting
743             my $loose; #
744             my $allow_barekey; # bareKey
745             my $allow_tags;
746              
747             my $alt_true;
748             my $alt_false;
749              
750             sub _detect_utf_encoding {
751 12410     12410   22657 my $text = shift;
752 12410         40151 my @octets = unpack('C4', $text);
753 12410 100       31125 return 'unknown' unless defined $octets[3];
754 12390 0 100     53061 return ( $octets[0] and $octets[1]) ? 'UTF-8'
    50 66        
    50 33        
    100          
    100          
755             : (!$octets[0] and $octets[1]) ? 'UTF-16BE'
756             : (!$octets[0] and !$octets[1]) ? 'UTF-32BE'
757             : ( $octets[2] ) ? 'UTF-16LE'
758             : (!$octets[2] ) ? 'UTF-32LE'
759             : 'unknown';
760             }
761              
762             sub PP_decode_json {
763 25269     25269 0 40365 my ($self, $want_offset);
764              
765 25269         64023 ($self, $text, $want_offset) = @_;
766              
767 25269         52400 ($at, $ch, $depth) = (0, '', 0);
768              
769 25269 100 100     107401 if ( !defined $text or ref $text ) {
770 4         9 decode_error("malformed JSON string, neither array, object, number, string or atom");
771             }
772              
773 25265         43689 my $props = $self->{PROPS};
774              
775             ($utf8, $relaxed, $loose, $allow_bignum, $allow_barekey, $singlequote, $allow_tags)
776 25265         42067 = @{$props}[P_UTF8, P_RELAXED, P_LOOSE .. P_ALLOW_SINGLEQUOTE, P_ALLOW_TAGS];
  25265         63697  
777              
778 25265         61946 ($alt_true, $alt_false) = @$self{qw/true false/};
779              
780 25265 100       47286 if ( $utf8 ) {
781 12410         28940 $encoding = _detect_utf_encoding($text);
782 12410 100 100     39047 if ($encoding ne 'UTF-8' and $encoding ne 'unknown') {
783 3         563 require Encode;
784 3         9658 Encode::from_to($text, $encoding, 'utf-8');
785             } else {
786 12407 100       36787 utf8::downgrade( $text, 1 ) or Carp::croak("Wide character in subroutine entry");
787             }
788             }
789             else {
790 12855         60498 utf8::encode( $text );
791             }
792              
793 25264         42858 $len = length $text;
794              
795             ($max_depth, $max_size, $cb_object, $cb_sk_object, $F_HOOK)
796 25264         38738 = @{$self}{qw/max_depth max_size cb_object cb_sk_object F_HOOK/};
  25264         62302  
797              
798 25264 100       51285 if ($max_size > 1) {
799 64     64   40814 use bytes;
  64         992  
  64         417  
800 2         6 my $bytes = length $text;
801 2 100       27 decode_error(
802             sprintf("attempted decode of JSON text of %s bytes size, but max_size is set to %s"
803             , $bytes, $max_size), 1
804             ) if ($bytes > $max_size);
805             }
806              
807 25263         57840 white(); # remove head white space
808              
809 25263 100       52200 decode_error("malformed JSON string, neither array, object, number, string or atom") unless defined $ch; # Is there a first character for JSON structure?
810              
811 25261         47322 my $result = value();
812              
813 25184 100 100     94797 if ( !$props->[ P_ALLOW_NONREF ] and !ref $result ) {
814 5         23 decode_error(
815             'JSON text must be an object or array (but found number, string, true, false or null,'
816             . ' use allow_nonref to allow this)', 1);
817             }
818              
819 25179 50       51725 Carp::croak('something wrong.') if $len < $at; # we won't arrive here.
820              
821 25179 100       48979 my $consumed = defined $ch ? $at - 1 : $at; # consumed JSON text length
822              
823 25179         50473 white(); # remove tail white space
824              
825 25179 100       49017 return ( $result, $consumed ) if $want_offset; # all right if decode_prefix
826              
827 24875 100       45987 decode_error("garbage after JSON object") if defined $ch;
828              
829 24863         196506 $result;
830             }
831              
832              
833             sub next_chr {
834 36720055 100   36720055 0 54913345 return $ch = undef if($at >= $len);
835 36694985         64496768 $ch = substr($text, $at++, 1);
836             }
837              
838              
839             sub value {
840 53833     53833 0 99039 white();
841 53833 50       93419 return if(!defined $ch);
842 53833 100       96010 return object() if($ch eq '{');
843 52443 100       106663 return array() if($ch eq '[');
844 26328 100       50207 return tag() if($ch eq '(');
845 26327 100 66     75718 return string() if($ch eq '"' or ($singlequote and $ch eq "'"));
      100        
846 905 100 100     3005 return number() if($ch =~ /[0-9]/ or $ch eq '-');
847 93         192 return word();
848             }
849              
850             sub string {
851 27152     27152 1 39309 my $utf16;
852             my $is_utf8;
853              
854 27152         46469 ($is_valid_utf8, $utf8_len) = ('', 0);
855              
856 27152         39829 my $s = ''; # basically UTF8 flag on
857              
858 27152 100 66     57728 if($ch eq '"' or ($singlequote and $ch eq "'")){
      100        
859 27147         37882 my $boundChar = $ch;
860              
861 27147         40760 OUTER: while( defined(next_chr()) ){
862              
863 10715493 100       20584057 if($ch eq $boundChar){
    100          
864 27131         56671 next_chr();
865              
866 27131 100       50368 if ($utf16) {
867 1         2 decode_error("missing low surrogate character in surrogate pair");
868             }
869              
870 27130 100       131813 utf8::decode($s) if($is_utf8);
871              
872 27130         124644 return $s;
873             }
874             elsif($ch eq '\\'){
875 5300299         8825761 next_chr();
876 5300299 100       9145219 if(exists $escapes{$ch}){
    100          
877 152492         254368 $s .= $escapes{$ch};
878             }
879             elsif($ch eq 'u'){ # UNICODE handling
880 5147803         6110161 my $u = '';
881              
882 5147803         7496722 for(1..4){
883 20591212         26537110 $ch = next_chr();
884 20591212 50       47199025 last OUTER if($ch !~ /[0-9a-fA-F]/);
885 20591212         29824105 $u .= $ch;
886             }
887              
888             # U+D800 - U+DBFF
889 5147803 100       11488046 if ($u =~ /^[dD][89abAB][0-9a-fA-F]{2}/) { # UTF-16 high surrogate?
    100          
890 1127978         1949244 $utf16 = $u;
891             }
892             # U+DC00 - U+DFFF
893             elsif ($u =~ /^[dD][c-fC-F][0-9a-fA-F]{2}/) { # UTF-16 low surrogate?
894 1127977 100       1794343 unless (defined $utf16) {
895 1         3 decode_error("missing high surrogate character in surrogate pair");
896             }
897 1127976         1291745 $is_utf8 = 1;
898 1127976   50     1670733 $s .= JSON_PP_decode_surrogates($utf16, $u) || next;
899 1127976         2076740 $utf16 = undef;
900             }
901             else {
902 2891848 100       4499171 if (defined $utf16) {
903 1         4 decode_error("surrogate pair expected");
904             }
905              
906 2891847         3881239 my $hex = hex( $u );
907 2891847 50       4777760 if ( chr $u =~ /[[:^ascii:]]/ ) {
908 2891847         3260574 $is_utf8 = 1;
909 2891847   50     4166713 $s .= JSON_PP_decode_unicode($u) || next;
910             }
911             else {
912 0         0 $s .= chr $hex;
913             }
914             }
915              
916             }
917             else{
918 4 50       9 unless ($loose) {
919 4         6 $at -= 2;
920 4         7 decode_error('illegal backslash escape sequence in string');
921             }
922 0         0 $s .= $ch;
923             }
924             }
925             else{
926              
927 5388063 100       11099940 if ( $ch =~ /[[:^ascii:]]/ ) {
928 3441000 100       4988611 unless( $ch = is_valid_utf8($ch) ) {
929 5         9 $at -= 1;
930 5         14 decode_error("malformed UTF-8 character in JSON string");
931             }
932             else {
933 3440995         4715067 $at += $utf8_len - 1;
934             }
935              
936 3440995         4325236 $is_utf8 = 1;
937             }
938              
939 5388058 50       8189073 if (!$loose) {
940 5388058 100       14739347 if ($ch =~ $invalid_char_re) { # '/' ok
941 4 50 33     12 if (!$relaxed or $ch ne "\t") {
942 4         5 $at--;
943 4         26 decode_error(sprintf "invalid character 0x%X"
944             . " encountered while parsing JSON string",
945             ord $ch);
946             }
947             }
948             }
949              
950 5388054         8734634 $s .= $ch;
951             }
952             }
953             }
954              
955 6         37 decode_error("unexpected end of string while parsing JSON string");
956             }
957              
958              
959             sub white {
960 162105     162105 0 284810 while( defined $ch ){
961 164722 100 100     602247 if($ch eq '' or $ch =~ /\A[ \t\r\n]\z/){
    50 66        
962 27669         46963 next_chr();
963             }
964             elsif($relaxed and $ch eq '/'){
965 0         0 next_chr();
966 0 0 0     0 if(defined $ch and $ch eq '/'){
    0 0        
967 0   0     0 1 while(defined(next_chr()) and $ch ne "\n" and $ch ne "\r");
      0        
968             }
969             elsif(defined $ch and $ch eq '*'){
970 0         0 next_chr();
971 0         0 while(1){
972 0 0       0 if(defined $ch){
973 0 0       0 if($ch eq '*'){
974 0 0 0     0 if(defined(next_chr()) and $ch eq '/'){
975 0         0 next_chr();
976 0         0 last;
977             }
978             }
979             else{
980 0         0 next_chr();
981             }
982             }
983             else{
984 0         0 decode_error("Unterminated comment");
985             }
986             }
987 0         0 next;
988             }
989             else{
990 0         0 $at--;
991 0         0 decode_error("malformed JSON string, neither array, object, number, string or atom");
992             }
993             }
994             else{
995 137053 100 100     244499 if ($relaxed and $ch eq '#') { # correctly?
996 9         28 pos($text) = $at;
997 9         38 $text =~ /\G([^\n]*(?:\r\n|\r|\n|$))/g;
998 9         16 $at = pos($text);
999 9         19 next_chr;
1000 9         19 next;
1001             }
1002              
1003 137044         192535 last;
1004             }
1005             }
1006             }
1007              
1008              
1009             sub array {
1010 26115   50 26115 1 85037 my $a = $_[0] || []; # you can use this code to use another array ref object.
1011              
1012 26115 100       54835 decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
1013             if (++$depth > $max_depth);
1014              
1015 26112         52408 next_chr();
1016 26112         53598 white();
1017              
1018 26112 100 66     84594 if(defined $ch and $ch eq ']'){
1019 23         43 --$depth;
1020 23         53 next_chr();
1021 23         61 return $a;
1022             }
1023             else {
1024 26089         51390 while(defined($ch)){
1025 26846         53891 push @$a, value();
1026              
1027 26279         65320 white();
1028              
1029 26279 100       54523 if (!defined $ch) {
1030 3         7 last;
1031             }
1032              
1033 26276 100       53103 if($ch eq ']'){
1034 25514         33771 --$depth;
1035 25514         50450 next_chr();
1036 25514         58051 return $a;
1037             }
1038              
1039 762 100       1302 if($ch ne ','){
1040 3         5 last;
1041             }
1042              
1043 759         1328 next_chr();
1044 759         1347 white();
1045              
1046 759 100 100     1757 if ($relaxed and $ch eq ']') {
1047 2         5 --$depth;
1048 2         16 next_chr();
1049 2         8 return $a;
1050             }
1051              
1052             }
1053             }
1054              
1055 6 100 66     28 $at-- if defined $ch and $ch ne '';
1056 6         14 decode_error(", or ] expected while parsing array");
1057             }
1058              
1059             sub tag {
1060 1 50   1 0 4 decode_error('malformed JSON string, neither array, object, number, string or atom') unless $allow_tags;
1061              
1062 1         3 next_chr();
1063 1         2 white();
1064              
1065 1         6 my $tag = value();
1066 1 50       4 return unless defined $tag;
1067 1 50       3 decode_error('malformed JSON string, (tag) must be a string') if ref $tag;
1068              
1069 1         3 white();
1070              
1071 1 50 33     31 if (!defined $ch or $ch ne ')') {
1072 0         0 decode_error(') expected after tag');
1073             }
1074              
1075 1         4 next_chr();
1076 1         3 white();
1077              
1078 1         3 my $val = value();
1079 1 50       13 return unless defined $val;
1080 1 50       7 decode_error('malformed JSON string, tag value must be an array') unless ref $val eq 'ARRAY';
1081              
1082 1 50       2 if (!eval { $tag->can('THAW') }) {
  1         10  
1083 0 0       0 decode_error('cannot decode perl-object (package does not exist)') if $@;
1084 0         0 decode_error('cannot decode perl-object (package does not have a THAW method)');
1085             }
1086 1         9 $tag->THAW('JSON', @$val);
1087             }
1088              
1089             sub object {
1090 1390   50 1390 1 4063 my $o = $_[0] || {}; # you can use this code to use another hash ref object.
1091 1390         1894 my $k;
1092              
1093 1390 50       2419 decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
1094             if (++$depth > $max_depth);
1095 1390         2452 next_chr();
1096 1390         2564 white();
1097              
1098 1390 100 66     3773 if(defined $ch and $ch eq '}'){
1099 9         14 --$depth;
1100 9         24 next_chr();
1101 9 100       35 if ($F_HOOK) {
1102 1         5 return _json_object_hook($o);
1103             }
1104 8         21 return $o;
1105             }
1106             else {
1107 1381         2331 while (defined $ch) {
1108 1732 100 66     4151 $k = ($allow_barekey and $ch ne '"' and $ch ne "'") ? bareKey() : string();
1109 1727         3311 white();
1110              
1111 1727 100 100     4893 if(!defined $ch or $ch ne ':'){
1112 3         5 $at--;
1113 3         21 decode_error("':' expected");
1114             }
1115              
1116 1724         3214 next_chr();
1117 1724         3330 $o->{$k} = value();
1118 1207         2477 white();
1119              
1120 1207 100       2048 last if (!defined $ch);
1121              
1122 1205 100       2110 if($ch eq '}'){
1123 847         1017 --$depth;
1124 847         1562 next_chr();
1125 847 100       1362 if ($F_HOOK) {
1126 8         14 return _json_object_hook($o);
1127             }
1128 839         2240 return $o;
1129             }
1130              
1131 358 100       628 if($ch ne ','){
1132 5         16 last;
1133             }
1134              
1135 353         659 next_chr();
1136 353         641 white();
1137              
1138 353 100 66     865 if ($relaxed and $ch eq '}') {
1139 1         2 --$depth;
1140 1         3 next_chr();
1141 1 50       36 if ($F_HOOK) {
1142 0         0 return _json_object_hook($o);
1143             }
1144 1         6 return $o;
1145             }
1146              
1147             }
1148              
1149             }
1150              
1151 8 100 66     64 $at-- if defined $ch and $ch ne '';
1152 8         33 decode_error(", or } expected while parsing object/hash");
1153             }
1154              
1155              
1156             sub bareKey { # doesn't strictly follow Standard ECMA-262 3rd Edition
1157 2     2 0 5 my $key;
1158 2         10 while($ch =~ /[\$\w[:^ascii:]]/){
1159 6         11 $key .= $ch;
1160 6         9 next_chr();
1161             }
1162 2         6 return $key;
1163             }
1164              
1165              
1166             sub word {
1167 93     93 0 198 my $word = substr($text,$at-1,4);
1168              
1169 93 100       309 if($word eq 'true'){
    100          
    100          
1170 14         22 $at += 3;
1171 14         27 next_chr;
1172 14 100       60 return defined $alt_true ? $alt_true : $JSON::PP::true;
1173             }
1174             elsif($word eq 'null'){
1175 44         61 $at += 3;
1176 44         91 next_chr;
1177 44         129 return undef;
1178             }
1179             elsif($word eq 'fals'){
1180 11         30 $at += 3;
1181 11 50       33 if(substr($text,$at,1) eq 'e'){
1182 11         17 $at++;
1183 11         23 next_chr;
1184 11 100       36 return defined $alt_false ? $alt_false : $JSON::PP::false;
1185             }
1186             }
1187              
1188 24         68 $at--; # for decode_error report
1189              
1190 24 100       64 decode_error("'null' expected") if ($word =~ /^n/);
1191 23 100       58 decode_error("'true' expected") if ($word =~ /^t/);
1192 22 50       57 decode_error("'false' expected") if ($word =~ /^f/);
1193 22         61 decode_error("malformed JSON string, neither array, object, number, string or atom");
1194             }
1195              
1196              
1197             sub number {
1198 812     812 1 1282 my $n = '';
1199 812         1696 my $v;
1200             my $is_dec;
1201 812         0 my $is_exp;
1202              
1203 812 100       1514 if($ch eq '-'){
1204 41         66 $n = '-';
1205 41         90 next_chr;
1206 41 100 66     224 if (!defined $ch or $ch !~ /\d/) {
1207 1         3 decode_error("malformed number (no digits after initial minus)");
1208             }
1209             }
1210              
1211             # According to RFC4627, hex or oct digits are invalid.
1212 811 100       1412 if($ch eq '0'){
1213 46         93 my $peek = substr($text,$at,1);
1214 46 100       151 if($peek =~ /^[0-9a-dfA-DF]/){ # e may be valid (exponential)
1215 5         25 decode_error("malformed number (leading zero must not be followed by another digit)");
1216             }
1217 41         74 $n .= $ch;
1218 41         61 next_chr;
1219             }
1220              
1221 806   100     2863 while(defined $ch and $ch =~ /\d/){
1222 971         1454 $n .= $ch;
1223 971         1456 next_chr;
1224             }
1225              
1226 806 100 100     2519 if(defined $ch and $ch eq '.'){
1227 49         85 $n .= '.';
1228 49         74 $is_dec = 1;
1229              
1230 49         104 next_chr;
1231 49 100 66     284 if (!defined $ch or $ch !~ /\d/) {
1232 1         5 decode_error("malformed number (no digits after decimal point)");
1233             }
1234             else {
1235 48         79 $n .= $ch;
1236             }
1237              
1238 48   100     95 while(defined(next_chr) and $ch =~ /\d/){
1239 97         181 $n .= $ch;
1240             }
1241             }
1242              
1243 805 100 100     2838 if(defined $ch and ($ch eq 'e' or $ch eq 'E')){
      100        
1244 58         150 $n .= $ch;
1245 58         83 $is_exp = 1;
1246 58         116 next_chr;
1247              
1248 58 100 100     324 if(defined($ch) and ($ch eq '+' or $ch eq '-')){
    100 100        
      100        
1249 38         74 $n .= $ch;
1250 38         71 next_chr;
1251 38 100 66     139 if (!defined $ch or $ch =~ /\D/) {
1252 2         50 decode_error("malformed number (no digits after exp sign)");
1253             }
1254 36         59 $n .= $ch;
1255             }
1256             elsif(defined($ch) and $ch =~ /\d/){
1257 18         37 $n .= $ch;
1258             }
1259             else {
1260 2         15 decode_error("malformed number (no digits after exp sign)");
1261             }
1262              
1263 54   100     87 while(defined(next_chr) and $ch =~ /\d/){
1264 33         60 $n .= $ch;
1265             }
1266              
1267             }
1268              
1269 801         1188 $v .= $n;
1270              
1271 801 100 100     2224 if ($is_dec or $is_exp) {
1272 70 100       163 if ($allow_bignum) {
1273 1         1282 require Math::BigFloat;
1274 1         27743 return Math::BigFloat->new($v);
1275             }
1276             } else {
1277 731 100       1477 if (length $v > $max_intsize) {
1278 1 50       3 if ($allow_bignum) { # from Adam Sussman
1279 1         8 require Math::BigInt;
1280 1         6 return Math::BigInt->new($v);
1281             }
1282             else {
1283 0         0 return "$v";
1284             }
1285             }
1286             }
1287              
1288 799 100       2533 return $is_dec ? $v/1.0 : 0+$v;
1289             }
1290              
1291             # Compute how many bytes are in the longest legal official Unicode
1292             # character
1293             my $max_unicode_length = do {
1294 64 50 33 64   248192 BEGIN { $] >= 5.006 and require warnings and warnings->unimport('utf8') }
1295             chr 0x10FFFF;
1296             };
1297             utf8::encode($max_unicode_length);
1298             $max_unicode_length = length $max_unicode_length;
1299              
1300             sub is_valid_utf8 {
1301              
1302             # Returns undef (setting $utf8_len to 0) unless the next bytes in $text
1303             # comprise a well-formed UTF-8 encoded character, in which case,
1304             # return those bytes, setting $utf8_len to their count.
1305              
1306 3441000     3441000 0 6690707 my $start_point = substr($text, $at - 1);
1307              
1308             # Look no further than the maximum number of bytes in a single
1309             # character
1310 3441000         4232764 my $limit = $max_unicode_length;
1311 3441000 100       5508497 $limit = length($start_point) if $limit > length($start_point);
1312              
1313             # Find the number of bytes comprising the first character in $text
1314             # (without having to know the details of its internal representation).
1315             # This loop will iterate just once on well-formed input.
1316 3441000         5447999 while ($limit > 0) { # Until we succeed or exhaust the input
1317 4681125         6143997 my $copy = substr($start_point, 0, $limit);
1318              
1319             # decode() will return true if all bytes are valid; false
1320             # if any aren't.
1321 4681125 100       8519523 if (utf8::decode($copy)) {
1322              
1323             # Is valid: get the first character, convert back to bytes,
1324             # and return those bytes.
1325 3440995         7033122 $copy = substr($copy, 0, 1);
1326 3440995         6519322 utf8::encode($copy);
1327 3440995         3924126 $utf8_len = length $copy;
1328 3440995         8078399 return substr($start_point, 0, $utf8_len);
1329             }
1330              
1331             # If it didn't work, it could be that there is a full legal character
1332             # followed by a partial or malformed one. Narrow the window and
1333             # try again.
1334 1240130         2019244 $limit--;
1335             }
1336              
1337             # Failed to find a legal UTF-8 character.
1338 5         10 $utf8_len = 0;
1339 5         24 return;
1340             }
1341              
1342              
1343             sub decode_error {
1344 101     101 0 222 my $error = shift;
1345 101         157 my $no_rep = shift;
1346 101 100       294 my $str = defined $text ? substr($text, $at) : '';
1347 101         150 my $mess = '';
1348 101         148 my $type = 'U*';
1349              
1350 101         124 if ( OLD_PERL ) {
1351             my $type = $] < 5.006 ? 'C*'
1352             : utf8::is_utf8( $str ) ? 'U*' # 5.6
1353             : 'C*'
1354             ;
1355             }
1356              
1357 101         572 for my $c ( unpack( $type, $str ) ) { # emulate pv_uni_display() ?
1358 458         765 my $chr_c = chr($c);
1359 458 50       1331 $mess .= $chr_c eq '\\' ? '\\\\'
    50          
    50          
    50          
    50          
    100          
    100          
1360             : $chr_c =~ /[[:print:]]/ ? $chr_c
1361             : $chr_c eq '\a' ? '\a'
1362             : $chr_c eq '\t' ? '\t'
1363             : $chr_c eq '\n' ? '\n'
1364             : $chr_c eq '\r' ? '\r'
1365             : $chr_c eq '\f' ? '\f'
1366             : sprintf('\x{%x}', $c)
1367             ;
1368 458 100       945 if ( length $mess >= 20 ) {
1369 10         19 $mess .= '...';
1370 10         20 last;
1371             }
1372             }
1373              
1374 101 100       299 unless ( length $mess ) {
1375 30         56 $mess = '(end of string)';
1376             }
1377              
1378             Carp::croak (
1379 101 100       35126 $no_rep ? "$error" : "$error, at character offset $at (before \"$mess\")"
1380             );
1381              
1382             }
1383              
1384              
1385             sub _json_object_hook {
1386 9     9   14 my $o = $_[0];
1387 9         10 my @ks = keys %{$o};
  9         29  
1388              
1389 9 100 66     61 if ( $cb_sk_object and @ks == 1 and exists $cb_sk_object->{ $ks[0] } and ref $cb_sk_object->{ $ks[0] } ) {
      100        
      66        
1390 4         14 my @val = $cb_sk_object->{ $ks[0] }->( $o->{$ks[0]} );
1391 4 100       19 if (@val == 0) {
    50          
1392 1         5 return $o;
1393             }
1394             elsif (@val == 1) {
1395 3         44 return $val[0];
1396             }
1397             else {
1398 0         0 Carp::croak("filter_json_single_key_object callbacks must not return more than one scalar");
1399             }
1400             }
1401              
1402 5 100       17 my @val = $cb_object->($o) if ($cb_object);
1403 5 100       17 if (@val == 0) {
    50          
1404 3         23 return $o;
1405             }
1406             elsif (@val == 1) {
1407 2         8 return $val[0];
1408             }
1409             else {
1410 0         0 Carp::croak("filter_json_object callbacks must not return more than one scalar");
1411             }
1412             }
1413              
1414              
1415             sub PP_decode_box {
1416             {
1417 0     0 0 0 text => $text,
1418             at => $at,
1419             ch => $ch,
1420             len => $len,
1421             depth => $depth,
1422             encoding => $encoding,
1423             is_valid_utf8 => $is_valid_utf8,
1424             };
1425             }
1426              
1427             } # PARSE
1428              
1429              
1430             sub _decode_surrogates { # from perlunicode
1431 1127976     1127976   1955751 my $uni = 0x10000 + (hex($_[0]) - 0xD800) * 0x400 + (hex($_[1]) - 0xDC00);
1432 1127976         2085040 my $un = pack('U*', $uni);
1433 1127976         2114540 utf8::encode( $un );
1434 1127976         2306177 return $un;
1435             }
1436              
1437              
1438             sub _decode_unicode {
1439 2891847     2891847   5257030 my $un = pack('U', hex shift);
1440 2891847         5411815 utf8::encode( $un );
1441 2891847         7613638 return $un;
1442             }
1443              
1444             #
1445             # Setup for various Perl versions (the code from JSON::PP58)
1446             #
1447              
1448             BEGIN {
1449              
1450 64 50   64   468 unless ( defined &utf8::is_utf8 ) {
1451 0         0 require Encode;
1452 0         0 *utf8::is_utf8 = *Encode::is_utf8;
1453             }
1454              
1455 64         142 if ( !OLD_PERL ) {
1456 64         261 *JSON::PP::JSON_PP_encode_ascii = \&_encode_ascii;
1457 64         141 *JSON::PP::JSON_PP_encode_latin1 = \&_encode_latin1;
1458 64         152 *JSON::PP::JSON_PP_decode_surrogates = \&_decode_surrogates;
1459 64         1722 *JSON::PP::JSON_PP_decode_unicode = \&_decode_unicode;
1460              
1461 64 50       338 if ($] < 5.008003) { # join() in 5.8.0 - 5.8.2 is broken.
1462             package JSON::PP;
1463 0         0 require subs;
1464 0         0 subs->import('join');
1465 0         0 eval q|
1466             sub join {
1467             return '' if (@_ < 2);
1468             my $j = shift;
1469             my $str = shift;
1470             for (@_) { $str .= $j . $_; }
1471             return $str;
1472             }
1473             |;
1474             }
1475             }
1476              
1477              
1478             sub JSON::PP::incr_parse {
1479 744     744 1 59165 local $Carp::CarpLevel = 1;
1480 744   66     2302 ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_parse( @_ );
1481             }
1482              
1483              
1484             sub JSON::PP::incr_skip {
1485 2   33 2 1 1745 ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_skip;
1486             }
1487              
1488              
1489             sub JSON::PP::incr_reset {
1490 0   0 0 1 0 ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_reset;
1491             }
1492              
1493 64 50 33 304 1 30419 eval q{
  304 50       53490  
  304         735  
  0         0  
  304         1564  
1494             sub JSON::PP::incr_text : lvalue {
1495             $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new;
1496              
1497             if ( $_[0]->{_incr_parser}->{incr_pos} ) {
1498             Carp::croak("incr_text cannot be called when the incremental parser already started parsing");
1499             }
1500             $_[0]->{_incr_parser}->{incr_text};
1501             }
1502             } if ( $] >= 5.006 );
1503              
1504             } # Setup for various Perl versions (the code from JSON::PP58)
1505              
1506              
1507             ###############################
1508             # Utilities
1509             #
1510              
1511             BEGIN {
1512 64     64   4280 eval 'require Scalar::Util';
1513 64 50       395 unless($@){
1514 64         219 *JSON::PP::blessed = \&Scalar::Util::blessed;
1515 64         150 *JSON::PP::reftype = \&Scalar::Util::reftype;
1516 64         7267 *JSON::PP::refaddr = \&Scalar::Util::refaddr;
1517             }
1518             else{ # This code is from Scalar::Util.
1519             # warn $@;
1520 0         0 eval 'sub UNIVERSAL::a_sub_not_likely_to_be_here { ref($_[0]) }';
1521             *JSON::PP::blessed = sub {
1522 0         0 local($@, $SIG{__DIE__}, $SIG{__WARN__});
1523 0 0       0 ref($_[0]) ? eval { $_[0]->a_sub_not_likely_to_be_here } : undef;
  0         0  
1524 0         0 };
1525 0         0 require B;
1526 0         0 my %tmap = qw(
1527             B::NULL SCALAR
1528             B::HV HASH
1529             B::AV ARRAY
1530             B::CV CODE
1531             B::IO IO
1532             B::GV GLOB
1533             B::REGEXP REGEXP
1534             );
1535             *JSON::PP::reftype = sub {
1536 0         0 my $r = shift;
1537              
1538 0 0       0 return undef unless length(ref($r));
1539              
1540 0         0 my $t = ref(B::svref_2object($r));
1541              
1542             return
1543 0 0       0 exists $tmap{$t} ? $tmap{$t}
    0          
1544             : length(ref($$r)) ? 'REF'
1545             : 'SCALAR';
1546 0         0 };
1547             *JSON::PP::refaddr = sub {
1548 0 0       0 return undef unless length(ref($_[0]));
1549              
1550 0         0 my $addr;
1551 0 0       0 if(defined(my $pkg = blessed($_[0]))) {
1552 0         0 $addr .= bless $_[0], 'Scalar::Util::Fake';
1553 0         0 bless $_[0], $pkg;
1554             }
1555             else {
1556 0         0 $addr .= $_[0]
1557             }
1558              
1559 0         0 $addr =~ /0x(\w+)/;
1560 0         0 local $^W;
1561             #no warnings 'portable';
1562 0         0 hex($1);
1563             }
1564 0         0 }
1565             }
1566              
1567              
1568             # shamelessly copied and modified from JSON::XS code.
1569              
1570             $JSON::PP::true = do { bless \(my $dummy = 1), "JSON::PP::Boolean" };
1571             $JSON::PP::false = do { bless \(my $dummy = 0), "JSON::PP::Boolean" };
1572              
1573             sub is_bool {
1574 5 100   5 1 1222 if (blessed $_[0]) {
1575             return (
1576 2   33     25 $_[0]->isa("JSON::PP::Boolean")
1577             or $_[0]->isa("Types::Serialiser::BooleanBase")
1578             or $_[0]->isa("JSON::XS::Boolean")
1579             );
1580             }
1581 0         0 elsif (CORE_BOOL) {
1582 64     64   8136 BEGIN { CORE_BOOL and warnings->unimport('experimental::builtin') }
1583             return builtin::is_bool($_[0]);
1584             }
1585 3         11 return !!0;
1586             }
1587              
1588 3     3 1 581 sub true { $JSON::PP::true }
1589 3     3 1 13 sub false { $JSON::PP::false }
1590 0     0 1 0 sub null { undef; }
1591              
1592             ###############################
1593              
1594             package JSON::PP::IncrParser;
1595              
1596 64     64   495 use strict;
  64         161  
  64         2079  
1597              
1598 64     64   403 use constant INCR_M_WS => 0; # initial whitespace skipping
  64         159  
  64         4852  
1599 64     64   424 use constant INCR_M_STR => 1; # inside string
  64         147  
  64         3366  
1600 64     64   989 use constant INCR_M_BS => 2; # inside backslash
  64         179  
  64         3378  
1601 64     64   413 use constant INCR_M_JSON => 3; # outside anything, count nesting
  64         157  
  64         3452  
1602 64     64   484 use constant INCR_M_C0 => 4;
  64         151  
  64         3334  
1603 64     64   408 use constant INCR_M_C1 => 5;
  64         156  
  64         3280  
1604 64     64   459 use constant INCR_M_TFN => 6;
  64         127  
  64         3328  
1605 64     64   392 use constant INCR_M_NUM => 7;
  64         168  
  64         20709  
1606              
1607             $JSON::PP::IncrParser::VERSION = '1.01';
1608              
1609             sub new {
1610 57     57   110 my ( $class ) = @_;
1611              
1612 57         398 bless {
1613             incr_nest => 0,
1614             incr_text => undef,
1615             incr_pos => 0,
1616             incr_mode => 0,
1617             }, $class;
1618             }
1619              
1620              
1621             sub incr_parse {
1622 744     744   1335 my ( $self, $coder, $text ) = @_;
1623              
1624 744 100       1496 $self->{incr_text} = '' unless ( defined $self->{incr_text} );
1625              
1626 744 100       1350 if ( defined $text ) {
1627 402         971 $self->{incr_text} .= $text;
1628             }
1629              
1630 744 100       2033 if ( defined wantarray ) {
1631 383         752 my $max_size = $coder->get_max_size;
1632 383         635 my $p = $self->{incr_pos};
1633 383         524 my @ret;
1634             {
1635 383         497 do {
  383         509  
1636 394 100 100     1472 unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) {
1637 393         961 $self->_incr_parse( $coder );
1638              
1639 392 100 100     845 if ( $max_size and $self->{incr_pos} > $max_size ) {
1640 1         107 Carp::croak("attempted decode of JSON text of $self->{incr_pos} bytes size, but max_size is set to $max_size");
1641             }
1642 391 100 100     1328 unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) {
1643             # as an optimisation, do not accumulate white space in the incr buffer
1644 83 100 100     252 if ( $self->{incr_mode} == INCR_M_WS and $self->{incr_pos} ) {
1645 7         14 $self->{incr_pos} = 0;
1646 7         11 $self->{incr_text} = '';
1647             }
1648 83         153 last;
1649             }
1650             }
1651              
1652 309 100       7602 unless ( $coder->get_utf8 ) {
1653 301         973 utf8::decode( $self->{incr_text} );
1654             }
1655              
1656 309         844 my ($obj, $offset) = $coder->PP_decode_json( $self->{incr_text}, 0x00000001 );
1657 298         563 push @ret, $obj;
1658 64     64   490 use bytes;
  64         288  
  64         393  
1659 298   50     867 $self->{incr_text} = substr( $self->{incr_text}, $offset || 0 );
1660 298         444 $self->{incr_pos} = 0;
1661 298         402 $self->{incr_nest} = 0;
1662 298         398 $self->{incr_mode} = 0;
1663 298 100       657 last unless wantarray;
1664             } while ( wantarray );
1665             }
1666              
1667 370 100       631 if ( wantarray ) {
1668 7         49 return @ret;
1669             }
1670             else { # in scalar context
1671 363 100       1448 return defined $ret[0] ? $ret[0] : undef;
1672             }
1673             }
1674             }
1675              
1676              
1677             sub _incr_parse {
1678 393     393   607 my ($self, $coder) = @_;
1679 393         937 my $text = $self->{incr_text};
1680 393         542 my $len = length $text;
1681 393         541 my $p = $self->{incr_pos};
1682              
1683             INCR_PARSE:
1684 393         778 while ( $len > $p ) {
1685 3084         4443 my $s = substr( $text, $p, 1 );
1686 3084 50       4720 last INCR_PARSE unless defined $s;
1687 3084         3771 my $mode = $self->{incr_mode};
1688              
1689 3084 100 100     11822 if ( $mode == INCR_M_WS ) {
    50          
    100          
    100          
    100          
    100          
    50          
1690 335         616 while ( $len > $p ) {
1691 594         812 $s = substr( $text, $p, 1 );
1692 594 50       960 last INCR_PARSE unless defined $s;
1693 594 100       1089 if ( ord($s) > ord " " ) {
1694 328 100       636 if ( $s eq '#' ) {
1695 6         12 $self->{incr_mode} = INCR_M_C0;
1696 6         15 redo INCR_PARSE;
1697             } else {
1698 322         432 $self->{incr_mode} = INCR_M_JSON;
1699 322         624 redo INCR_PARSE;
1700             }
1701             }
1702 266         403 $p++;
1703             }
1704             } elsif ( $mode == INCR_M_BS ) {
1705 0         0 $p++;
1706 0         0 $self->{incr_mode} = INCR_M_STR;
1707 0         0 redo INCR_PARSE;
1708             } elsif ( $mode == INCR_M_C0 or $mode == INCR_M_C1 ) {
1709 9         18 while ( $len > $p ) {
1710 45         59 $s = substr( $text, $p, 1 );
1711 45 50       73 last INCR_PARSE unless defined $s;
1712 45 100       71 if ( $s eq "\n" ) {
1713 9 100       16 $self->{incr_mode} = $self->{incr_mode} == INCR_M_C0 ? INCR_M_WS : INCR_M_JSON;
1714 9         15 last;
1715             }
1716 36         56 $p++;
1717             }
1718 9         14 next;
1719             } elsif ( $mode == INCR_M_TFN ) {
1720 36 50 66     78 last INCR_PARSE if $p >= $len && $self->{incr_nest};
1721 35         67 while ( $len > $p ) {
1722 140         216 $s = substr( $text, $p++, 1 );
1723 140 100 66     529 next if defined $s and $s =~ /[rueals]/;
1724 35         54 last;
1725             }
1726 35         45 $p--;
1727 35         53 $self->{incr_mode} = INCR_M_JSON;
1728              
1729 35 50       67 last INCR_PARSE unless $self->{incr_nest};
1730 35         44 redo INCR_PARSE;
1731             } elsif ( $mode == INCR_M_NUM ) {
1732 399 100 100     699 last INCR_PARSE if $p >= $len && $self->{incr_nest};
1733 396         635 while ( $len > $p ) {
1734 482         704 $s = substr( $text, $p++, 1 );
1735 482 100 66     1594 next if defined $s and $s =~ /[0-9eE.+\-]/;
1736 389         498 last;
1737             }
1738 396         462 $p--;
1739 396         554 $self->{incr_mode} = INCR_M_JSON;
1740              
1741 396 100       761 last INCR_PARSE unless $self->{incr_nest};
1742 378         497 redo INCR_PARSE;
1743             } elsif ( $mode == INCR_M_STR ) {
1744 805         1388 while ( $len > $p ) {
1745 84413         103192 $s = substr( $text, $p, 1 );
1746 84413 50       121444 last INCR_PARSE unless defined $s;
1747 84413 100       145591 if ( $s eq '"' ) {
    100          
1748 780         886 $p++;
1749 780         1091 $self->{incr_mode} = INCR_M_JSON;
1750              
1751 780 100       1327 last INCR_PARSE unless $self->{incr_nest};
1752 760         1066 redo INCR_PARSE;
1753             }
1754             elsif ( $s eq '\\' ) {
1755 508         617 $p++;
1756 508 50       828 if ( !defined substr($text, $p, 1) ) {
1757 0         0 $self->{incr_mode} = INCR_M_BS;
1758 0         0 last INCR_PARSE;
1759             }
1760             }
1761 83633         124354 $p++;
1762             }
1763             } elsif ( $mode == INCR_M_JSON ) {
1764 1500         2434 while ( $len > $p ) {
1765 3614         5263 $s = substr( $text, $p++, 1 );
1766 3614 50 66     20919 if ( $s eq "\x00" ) {
    100 100        
    100 100        
    100 100        
    100          
    100          
    100          
    100          
1767 0         0 $p--;
1768 0         0 last INCR_PARSE;
1769             } elsif ( $s =~ /^[\t\n\r ]$/) {
1770 724 50       1283 if ( !$self->{incr_nest} ) {
1771 0         0 $p--; # do not eat the whitespace, let the next round do it
1772 0         0 last INCR_PARSE;
1773             }
1774 724         1142 next;
1775             } elsif ( $s eq 't' or $s eq 'f' or $s eq 'n' ) {
1776 36         60 $self->{incr_mode} = INCR_M_TFN;
1777 36         53 redo INCR_PARSE;
1778             } elsif ( $s =~ /^[0-9\-]$/ ) {
1779 398         618 $self->{incr_mode} = INCR_M_NUM;
1780 398         606 redo INCR_PARSE;
1781             } elsif ( $s eq '"' ) {
1782 783         1099 $self->{incr_mode} = INCR_M_STR;
1783 783         1117 redo INCR_PARSE;
1784             } elsif ( $s eq '[' or $s eq '{' ) {
1785 383 100       827 if ( ++$self->{incr_nest} > $coder->get_max_depth ) {
1786 1         99 Carp::croak('json text or perl structure exceeds maximum nesting level (max_depth set too low?)');
1787             }
1788 382         770 next;
1789             } elsif ( $s eq ']' or $s eq '}' ) {
1790 369 100       833 if ( --$self->{incr_nest} <= 0 ) {
1791 270         424 last INCR_PARSE;
1792             }
1793             } elsif ( $s eq '#' ) {
1794 3         6 $self->{incr_mode} = INCR_M_C1;
1795 3         6 redo INCR_PARSE;
1796             }
1797             }
1798             }
1799             }
1800              
1801 392         570 $self->{incr_pos} = $p;
1802 392 100       966 $self->{incr_parsing} = $p ? 1 : 0; # for backward compatibility
1803             }
1804              
1805              
1806             sub incr_text {
1807 0 0   0   0 if ( $_[0]->{incr_pos} ) {
1808 0         0 Carp::croak("incr_text cannot be called when the incremental parser already started parsing");
1809             }
1810 0         0 $_[0]->{incr_text};
1811             }
1812              
1813              
1814             sub incr_skip {
1815 2     2   5 my $self = shift;
1816 2         7 $self->{incr_text} = substr( $self->{incr_text}, $self->{incr_pos} );
1817 2         4 $self->{incr_pos} = 0;
1818 2         5 $self->{incr_mode} = 0;
1819 2         5 $self->{incr_nest} = 0;
1820             }
1821              
1822              
1823             sub incr_reset {
1824 0     0     my $self = shift;
1825 0           $self->{incr_text} = undef;
1826 0           $self->{incr_pos} = 0;
1827 0           $self->{incr_mode} = 0;
1828 0           $self->{incr_nest} = 0;
1829             }
1830              
1831             ###############################
1832              
1833              
1834             1;
1835             __END__