File Coverage

blib/lib/JSON/WithComments.pm
Criterion Covered Total %
statement 21 41 51.2
branch 1 10 10.0
condition 0 5 0.0
subroutine 7 9 77.7
pod 3 3 100.0
total 32 68 47.0


line stmt bran cond sub pod time code
1             ###############################################################################
2             #
3             # This file copyright © 2017 by Randy J. Ray, all rights reserved
4             #
5             # See "LICENSE AND COPYRIGHT" in the POD for terms.
6             #
7             ###############################################################################
8             #
9             # Description: Simple support for comments in JSON content.
10             #
11             # Functions: import
12             # comment_style
13             # get_comment_style
14             # decode
15             #
16             # Libraries: JSON
17             #
18             # Global Consts: %PATTERNS
19             #
20             # Environment: None
21             #
22             ###############################################################################
23              
24             package JSON::WithComments;
25              
26 1     1   87873 use 5.008;
  1         5  
27 1     1   8 use strict;
  1         3  
  1         41  
28 1     1   8 use warnings;
  1         4  
  1         45  
29 1     1   8 use base qw(JSON);
  1         8  
  1         626  
30              
31 1     1   12296 use Carp ();
  1         3  
  1         439  
32              
33             our $VERSION = '0.001'; # VERSION
34              
35             # These regular expressions are adapted from Regexp::Common::comment.
36              
37             # The length of the regexp for JS multi-line comments triggers this:
38             ## no critic(RegularExpressions::RequireExtendedFormatting)
39             my $JS_SINGLE = qr{(?://)(?:[^\n]*)};
40             my $JS_MULTI = qr{(?:\/[*])(?:(?:[^*]+|[*](?!\/))*)(?:[*]\/)};
41             my $PERL = qr{(?:#)(?:[^\n]*)};
42             my %PATTERNS = (
43             perl => qr{(?
44             javascript => qr{(?
45             );
46              
47             # This is the comment-style that will be used if/when an object has not
48             # specified a style. It can be changed in import() with -default_comment_style.
49             # This is also the style that will be used by decode_json.
50             my $default_comment_style = 'javascript';
51              
52             sub import {
53 1     1   12 my ($class, @imports) = @_;
54              
55 1         2 my ($index, $style);
56 1         4 for my $idx (0 .. $#imports) {
57 0 0       0 if ($imports[$idx] eq '-default_comment_style') {
58 0         0 $index = $idx;
59 0         0 $style = $imports[$idx + 1];
60 0         0 last;
61             }
62             }
63 1 50       6 if (defined $index) {
64 0   0     0 $style ||= '(undef)';
65 0 0       0 if (! $PATTERNS{$style}) {
66 0         0 Carp::croak "Unknown comment style '$style' given as default";
67             }
68 0         0 $default_comment_style = $style;
69 0         0 splice @imports, $index, 2;
70             }
71              
72 1         8 return $class->SUPER::import(@imports);
73             }
74              
75             sub comment_style {
76 0     0 1 0 my ($self, $value) = @_;
77              
78 0 0       0 if (defined $value) {
79 0 0       0 if (! $PATTERNS{$value}) {
80 0         0 Carp::croak "Unknown comment_style ($value)";
81             }
82 0         0 $self->{comment_style} = $value;
83             }
84              
85 0         0 return $self;
86             }
87              
88             sub get_comment_style {
89 1     1 1 1670 my $self = shift;
90              
91 1   0     68 return $self->{comment_style} || $default_comment_style;
92             }
93              
94             sub decode {
95 0     0 1   my ($self, $text) = @_;
96              
97 0           my $comment_re = $PATTERNS{$self->get_comment_style};
98             # The JSON module reports errors using the character-offset within the
99             # string as a whole. So rather than deleting comments, replace them with a
100             # string of spaces of the same length. This should mean that any reported
101             # character offsets in the JSON data will still be correct.
102 0           $text =~ s/$comment_re/q{ } x length($1)/ge;
  0            
103              
104 0           return $self->SUPER::decode($text);
105             }
106              
107             1;
108              
109             __END__