File Coverage

blib/lib/App/DPath.pm
Criterion Covered Total %
statement 143 151 94.7
branch 64 74 86.4
condition 6 7 85.7
subroutine 22 22 100.0
pod 2 2 100.0
total 237 256 92.5


line stmt bran cond sub pod time code
1             package App::DPath;
2             # git description: v0.10-5-gd6d7a5e
3              
4             our $AUTHORITY = 'cpan:SCHWIGON';
5             # ABSTRACT: Cmdline tool around Data::DPath
6             $App::DPath::VERSION = '0.11';
7 2     2   137177 use 5.008; # Data::DPath requires it
  2         22  
8 2     2   12 use strict;
  2         3  
  2         40  
9 2     2   9 use warnings;
  2         3  
  2         50  
10              
11 2     2   9 use Scalar::Util 'reftype';
  2         4  
  2         1152  
12              
13             sub read_in
14             {
15             #my ($c, $file) = @_;
16 11     11 1 5258 my ($file, $intype, $yamlmod) = @_;
17              
18 11   100     56 $intype ||= 'yaml';
19 11         33 my $data;
20             my $filecontent;
21             {
22 11         21 local $/;
  11         48  
23 11 50       39 if ($file eq '-') {
24 0         0 $filecontent = ;
25             }
26             else
27             {
28 11 100       802 open (my $FH, "<", $file) or die "dpath: cannot open input file $file.\n";
29 10         406 $filecontent = <$FH>;
30 10         218 close $FH;
31             }
32             }
33              
34 10 100 66     115 if (not defined $filecontent or $filecontent !~ /[^\s\t\r\n]/ms) {
35 1         20 die "dpath: no meaningful input to read.\n";
36             }
37              
38 9 100       67 if ($intype eq "yaml") {
    100          
    100          
    100          
    100          
    100          
    100          
    50          
39 2         438 require YAML::Any;
40 2 50       1302 if ($yamlmod) {
41 0         0 @YAML::Any::_TEST_ORDER=($yamlmod);
42             } else {
43 2         7 @YAML::Any::_TEST_ORDER=(qw(YAML::XS YAML::Old YAML YAML::Tiny)); # no YAML::Syck
44             }
45 2         11 $data = [YAML::Any::Load($filecontent)];
46             }
47             elsif ($intype eq "json") {
48 1         11 require JSON;
49 1         157 $data = JSON::decode_json($filecontent);
50             }
51             elsif ($intype eq "xml")
52             {
53 1         11 require XML::Simple;
54 1         11 my $xs = new XML::Simple;
55 1         77 $data = $xs->XMLin($filecontent, KeepRoot => 1);
56             }
57             elsif ($intype eq "ini") {
58 1         11 require Config::INI::Serializer;
59 1         12 my $ini = Config::INI::Serializer->new;
60 1         9 $data = $ini->deserialize($filecontent);
61             }
62             elsif ($intype eq "cfggeneral") {
63 1         923 require Config::General;
64 1         24829 my %data = Config::General->new(-String => $filecontent,
65             -InterPolateVars => 1,
66             )->getall;
67 1         5762 $data = \%data;
68             }
69             elsif ($intype eq "dumper") {
70 1         804 eval '$data = my '.$filecontent;
71             }
72             elsif ($intype eq "tap") {
73 1         633 require TAP::DOM;
74 1         69312 require TAP::Parser;
75 1 50       14 $data = new TAP::DOM( tap => $filecontent, $TAP::Parser::VERSION > 3.22 ? (version => 13) : () );
76             }
77             elsif ($intype eq "taparchive") {
78 0         0 require TAP::DOM::Archive;
79 0         0 require TAP::Parser;
80 0 0       0 $data = new TAP::DOM::Archive( filecontent => $filecontent, $TAP::Parser::VERSION > 3.22 ? (version => 13) : () );
81             }
82             else
83             {
84 1         8 die "dpath: unrecognized input format: $intype.\n";
85             }
86 8         557933 return $data;
87             }
88              
89             sub _format_flat_inner_scalar
90             {
91 9     9   108 my ($result) = @_;
92              
93 2     2   14 no warnings 'uninitialized';
  2         4  
  2         168  
94              
95 9         41 return "$result";
96             }
97              
98             sub _format_flat_inner_array
99             {
100 9     9   18 my ($opt, $result) = @_;
101              
102 2     2   14 no warnings 'uninitialized';
  2         3  
  2         278  
103              
104             return
105             join($opt->{separator},
106             map {
107             # only SCALARS allowed (where reftype returns undef)
108 9 100       25 die "dpath: unsupported innermost nesting (".reftype($_).") for 'flat' output.\n" if defined reftype($_);
  11         46  
109 10         52 "".$_
110             } @$result);
111             }
112              
113             sub _format_flat_inner_hash
114             {
115 8     8   578 my ($opt, $result) = @_;
116              
117 2     2   14 no warnings 'uninitialized';
  2         4  
  2         295  
118              
119             return
120             join($opt->{separator},
121 8         31 map { my $v = $result->{$_};
  7         10  
122             # only SCALARS allowed (where reftype returns undef)
123 7 100       27 die "dpath: unsupported innermost nesting (".reftype($v).") for 'flat' output.\n" if defined reftype($v);
124 6         36 "$_=".$v
125             } keys %$result);
126             }
127              
128             sub _format_flat_outer
129             {
130 13     13   2209 my ($opt, $result) = @_;
131              
132 2     2   14 no warnings 'uninitialized';
  2         4  
  2         1762  
133              
134 13         24 my $output = "";
135 13 100       33 die "dpath: can not flatten data structure (undef) - try other output format.\n" unless defined $result;
136              
137 12 100       15 my $A = ""; my $B = ""; if ($opt->{fb}) { $A = "["; $B = "]" }
  12         17  
  12         27  
  4         5  
  4         6  
138 12         17 my $fi = $opt->{fi};
139              
140 12 100       78 if (!defined reftype $result) { # SCALAR
    50          
    100          
    100          
141 2         5 $output .= $result."\n"; # stringify
142             }
143             elsif (reftype $result eq 'SCALAR') { # blessed SCALAR
144 0         0 $output .= $result."\n"; # stringify
145             }
146             elsif (reftype $result eq 'ARRAY') {
147 5         14 for (my $i=0; $i<@$result; $i++) {
148 8         12 my $entry = $result->[$i];
149 8 100       16 my $prefix = $fi ? "$i:" : "";
150 8 100       29 if (!defined reftype $entry) { # SCALAR
    100          
    100          
151 3         7 $output .= $prefix.$A._format_flat_inner_scalar($entry)."$B\n";
152             }
153             elsif (reftype $entry eq 'ARRAY') {
154 2         7 $output .= $prefix.$A._format_flat_inner_array($opt, $entry)."$B\n";
155             }
156             elsif (reftype $entry eq 'HASH') {
157 2         5 $output .= $prefix.$A._format_flat_inner_hash($opt, $entry)."$B\n";
158             }
159             else {
160 1         8 die "dpath: can not flatten data structure (".reftype($entry).").\n";
161             }
162             }
163             }
164             elsif (reftype $result eq 'HASH') {
165 4         15 my @keys = keys %$result;
166 4         7 foreach my $key (@keys) {
167 5         9 my $entry = $result->{$key};
168 5 100       19 if (!defined reftype $entry) { # SCALAR
    100          
    100          
169 2         5 $output .= "$key:"._format_flat_inner_scalar($entry)."\n";
170             }
171             elsif (reftype $entry eq 'ARRAY') {
172 1         4 $output .= "$key:"._format_flat_inner_array($opt, $entry)."\n";
173             }
174             elsif (reftype $entry eq 'HASH') {
175 1         4 $output .= "$key:"._format_flat_inner_hash($opt, $entry)."\n";
176             }
177             else {
178 1         8 die "dpath: can not flatten data structure (".reftype($entry).").\n";
179             }
180             }
181             }
182             else {
183 1         8 die "dpath: can not flatten data structure (".reftype($result).") - try other output format.\n";
184             }
185              
186 9         35 return $output;
187             }
188              
189             sub _format_flat
190             {
191 1     1   536 my ($opt, $resultlist) = @_;
192              
193 1         2 my $output = "";
194 1 50       5 $opt->{separator} = ";" unless defined $opt->{separator};
195 1         4 $output .= _format_flat_outer($opt, $_) foreach @$resultlist;
196 1         5 return $output;
197             }
198              
199             sub write_out
200             {
201 36     36 1 14300 my ($opt, $resultlist) = @_;
202              
203 36         75 my $output = "";
204 36   100     119 my $outtype = $opt->{outtype} || 'yaml';
205 36 100       163 if ($outtype eq "yaml")
    100          
    100          
    100          
    100          
    50          
206             {
207 8         83 require YAML::Any;
208 8 50       36 if ($opt->{'yaml-module'}) {
209 0         0 @YAML::Any::_TEST_ORDER=($opt->{'yaml-module'});
210             } else {
211 8         36 @YAML::Any::_TEST_ORDER=(qw(YAML::XS YAML::Old YAML YAML::Tiny)); # no YAML::Syck
212             }
213 8         45 $output .= YAML::Any::Dump($resultlist);
214             }
215             elsif ($outtype eq "json")
216             {
217 7     1   714 eval "use JSON -convert_blessed_universally";
  1     1   639  
  1     1   8495  
  1     1   8  
  1     1   7  
  1     1   2  
  1     1   10  
  1         7  
  1         2  
  1         10  
  1         8  
  1         3  
  1         9  
  1         41  
  1         4  
  1         33  
  1         7  
  1         2  
  1         9  
  1         7  
  1         3  
  1         10  
218 7         1306 my $json = JSON->new->allow_nonref->pretty->allow_blessed->convert_blessed;
219 7         179 $output .= $json->encode($resultlist);
220             }
221             elsif ($outtype eq "ini") {
222 6         608 require Config::INI::Serializer;
223 6         1449 my $ini = Config::INI::Serializer->new;
224 6         48 $output .= $ini->serialize($resultlist);
225             }
226             elsif ($outtype eq "dumper")
227             {
228 7         65 require Data::Dumper;
229 7         44 $output .= Data::Dumper::Dumper($resultlist);
230             }
231             elsif ($outtype eq "xml")
232             {
233 7         840 require XML::Simple;
234 7         8854 my $xs = new XML::Simple;
235 7         541 $output .= $xs->XMLout($resultlist, AttrIndent => 1, KeepRoot => 1);
236             }
237             elsif ($outtype eq "flat") {
238 0         0 $output .= _format_flat( $opt, $resultlist );
239             }
240             else
241             {
242 1         8 die "dpath: unrecognized output format: $outtype.";
243             }
244 35         767825 return $output;
245             }
246              
247              
248              
249             1;
250              
251             __END__