File Coverage

blib/lib/Filename/Type/Compressed.pm
Criterion Covered Total %
statement 27 27 100.0
branch 7 8 87.5
condition 2 2 100.0
subroutine 5 5 100.0
pod 1 1 100.0
total 42 43 97.6


line stmt bran cond sub pod time code
1             package Filename::Type::Compressed;
2              
3 2     2   315702 use 5.010001;
  2         7  
4 2     2   53 use strict;
  2         4  
  2         67  
5 2     2   20 use warnings;
  2         7  
  2         107  
6              
7 2     2   7 use Exporter qw(import);
  2         2  
  2         1432  
8              
9             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
10             our $DATE = '2024-12-20'; # DATE
11             our $DIST = 'Filename-Type-Compressed'; # DIST
12             our $VERSION = '0.051'; # VERSION
13              
14             our @EXPORT_OK = qw(check_compressed_filename);
15             #list_compressor_suffixes
16              
17             our %SUFFIXES = (
18             '.Z' => {name=>'NCompress'},
19             '.gz' => {name=>'Gzip'},
20             '.bz2' => {name=>'Bzip2'},
21             '.xz' => {name=>'XZ'},
22             '.lz' => {name=>'LZ'},
23             '.lzma'=> {name=>'LZMA'},
24             '.zst' => {name=>'Zstandard'},
25             '.br' => {name=>'Brotli'},
26             );
27              
28             our %COMPRESSORS = (
29             NCompress => {
30             # all programs mentioned here must accept filename(s) as arguments.
31             # preferably CLI.
32             compressor_programs => [
33             {name => 'compress', opts => ''},
34             ],
35             decompressor_programs => [
36             {name => 'uncompress', opts => ''},
37             ],
38             },
39             Gzip => {
40             compressor_programs => [
41             {name => 'gzip', opts => ''},
42             ],
43             decompressor_programs => [
44             {name => 'gzip', opts => '-d'},
45             {name => 'gunzip', opts => ''},
46             ],
47             },
48             Bzip2 => {
49             compressor_programs => [
50             {name => 'bzip2', opts => ''},
51             ],
52             decompressor_programs => [
53             {name => 'bzip2', opts => '-d'},
54             {name => 'bunzip2', opts => ''},
55             ],
56             },
57             XZ => {
58             compressor_programs => [
59             {name => 'xz', opts => ''},
60             ],
61             decompressor_programs => [
62             {name => 'xz', opts => '-d'},
63             {name => 'unxz', opts => ''},
64             ],
65             },
66             Zstandard => {
67             compressor_programs => [
68             {name => 'zstd', opts => ''},
69             ],
70             decompressor_programs => [
71             {name => 'zstd', opts => '-d'},
72             {name => 'unzstd', opts => ''},
73             ],
74             },
75             Brotli => {
76             compressor_programs => [
77             ],
78             decompressor_programs => [
79             ],
80             },
81             LZ => {
82             compressor_programs => [
83             ],
84             decompressor_programs => [
85             ],
86             },
87             LZMA => {
88             compressor_programs => [
89             {name => 'lzma', opts => ''},
90             ],
91             decompressor_programs => [
92             {name => 'lzma', opts => '-d'},
93             {name => 'unlzma', opts => ''},
94             ],
95             },
96             );
97              
98             our %SPEC;
99              
100             $SPEC{check_compressed_filename} = {
101             v => 1.1,
102             summary => 'Check whether filename indicates being compressed',
103             description => <<'_',
104              
105              
106             _
107             args => {
108             filename => {
109             schema => 'str*',
110             req => 1,
111             pos => 0,
112             },
113             # recurse?
114             ignore_case => {
115             summary => 'Whether to match case-insensitively',
116             schema => 'bool',
117             default => 1,
118             },
119             },
120             result_naked => 1,
121             result => {
122             schema => ['any*', of=>['bool*', 'hash*']],
123             description => <<'_',
124              
125             Return false if no compressor suffixes detected. Otherwise return a hash of
126             information, which contains these keys: `compressor_name`, `compressor_suffix`,
127             `uncompressed_filename`.
128              
129             _
130             },
131             examples => [
132             {
133             args => {filename=>'foo.bar'},
134             },
135             {
136             args => {filename=>'baz.xz'},
137             },
138             {
139             args => {filename=>'qux.Bz2'},
140             },
141             ],
142             };
143             sub check_compressed_filename {
144 7     7 1 414301 my %args = @_;
145              
146 7         14 my $filename = $args{filename};
147 7 50       49 $filename =~ /(\.\w+)\z/ or return 0;
148 7   100     30 my $ci = $args{ignore_case} // 1;
149              
150 7         16 my $suffix = $1;
151              
152 7         35 my $spec;
153 7 100       16 if ($ci) {
154 6         15 my $suffix_lc = lc($suffix);
155 6         21 for (keys %SUFFIXES) {
156 32 100       69 if (lc($_) eq $suffix_lc) {
157 5         10 $spec = $SUFFIXES{$_};
158 5         11 last;
159             }
160             }
161             } else {
162 1         3 $spec = $SUFFIXES{$suffix};
163             }
164 7 100       28 return 0 unless $spec;
165              
166 5         37 (my $ufilename = $filename) =~ s/\.\w+\z//;
167              
168             return {
169             compressor_name => $spec->{name},
170 5         52 compressor_suffix => $suffix,
171             uncompressed_filename => $ufilename,
172             };
173             }
174              
175             1;
176             # ABSTRACT: Check whether filename indicates being compressed
177              
178             __END__