File Coverage

lib/Text/FixEOL.pm
Criterion Covered Total %
statement 152 152 100.0
branch 64 64 100.0
condition 15 15 100.0
subroutine 18 18 100.0
pod 13 13 100.0
total 262 262 100.0


line stmt bran cond sub pod time code
1             package Text::FixEOL;
2              
3 1     1   71289 use strict;
  1         2  
  1         104  
4 1     1   6 use warnings;
  1         2  
  1         1864  
5              
6             $Text::FixEOL::VERSION = '1.08';
7              
8             ##########################################################################################
9              
10             my %_Platform_Defaults = (
11             lf => {
12             'fixlast' => 'no',
13             'eof' => 'asis',
14             'eol' => "\012",
15             },
16             cr => {
17             'fixlast' => 'no',
18             'eof' => 'asis',
19             'eol' => "\015",
20             },
21             crlf => {
22             'fixlast' => 'no',
23             'eof' => 'asis',
24             'eol' => "\015\012",
25             },
26             asis => {
27             'fixlast' => 'no',
28             'eof' => 'asis',
29             'eol' => "asis",
30             },
31             network => {
32             'fixlast' => 'yes',
33             'eof' => 'remove',
34             'eol' => "\015\012",
35             },
36             mac => {
37             'fixlast' => 'yes',
38             'eof' => 'remove',
39             'eol' => "\015",
40             },
41             macos => {
42             'fixlast' => 'yes',
43             'eof' => 'remove',
44             'eol' => "\015",
45             },
46             windows => {
47             'fixlast' => 'yes',
48             'eof' => 'asis',
49             'eol' => "\015\012",
50             },
51             mswin32 => {
52             'fixlast' => 'yes',
53             'eof' => 'asis',
54             'eol' => "\015\012",
55             },
56             os2 => {
57             'fixlast' => 'yes',
58             'eof' => 'asis',
59             'eol' => "\015\012",
60             },
61             vms => {
62             'fixlast' => 'yes',
63             'eof' => 'remove',
64             'eol' => "\015\012",
65             },
66             netware => {
67             'fixlast' => 'yes',
68             'eof' => 'asis',
69             'eol' => "\015\012",
70             },
71             dos => {
72             'fixlast' => 'yes',
73             'eof' => 'asis',
74             'eol' => "\015\012",
75             },
76             cygwin => {
77             'fixlast' => 'yes',
78             'eof' => 'asis',
79             'eol' => "\015\012",
80             },
81             unix => {
82             'fixlast' => 'yes',
83             'eof' => 'remove',
84             'eol' => "\012",
85             },
86             'unknown' => {
87             'fixlast' => 'yes',
88             'eof' => 'remove',
89             'eol' => "\n",
90             },
91             );
92              
93             ##########################################################################################
94              
95             sub new {
96 322     322 1 6359 my $proto = shift;
97 322         359 my $proto_ref = ref($proto);
98 322         272 my $package = __PACKAGE__;
99 322         277 my $class;
100 322 100       362 if ($proto_ref) { $class = $proto_ref; }
  296 100       292  
101 25         26 elsif ($proto) { $class = $proto; }
102 1         2 else { $class = $package; }
103 322         374 my $self = bless {},$class;
104              
105 322         476 $self->eol_handling('platform');
106 322         394 $self->eof_handling('platform');
107 322         419 $self->fix_last_handling('platform');
108              
109 322         290 my %raw_properties = ();
110 322 100       452 if (1 < @_) { %raw_properties = @_; }
  4 100       10  
111             elsif (1 == @_) {
112 301         276 my $parm = shift;
113 301         298 my $parm_type = ref($parm);
114 301 100       339 if ($parm_type eq 'HASH') {
115 300         738 %raw_properties = %$parm;
116             } else {
117 1         5 require Carp;
118 1         71 Carp::croak("${package}::new() - Unexpected parameter type passed to constructor: $parm_type");
119             }
120             } else {
121 17         35 return $self;
122             }
123              
124 304         540 my %properties = map { lc($_) => $raw_properties{$_} } keys %raw_properties;
  900         1547  
125              
126 304 100       517 if ($properties{'eol'}) {
127 302         446 $self->eol_handling($properties{'eol'});
128 302         343 delete $properties{'eol'};
129             }
130 304 100       359 if ($properties{'eof'}) {
131 298         399 $self->eof_handling($properties{'eof'});
132 298         303 delete $properties{'eof'};
133             }
134 304 100       424 if ($properties{'fixlast'}) {
135 298         408 $self->fix_last_handling($properties{'fixlast'});
136 298         269 delete $properties{'fixlast'};
137             }
138 304         337 my @extra_properties = keys %properties;
139 304 100       412 if (0 < @extra_properties) {
140 2         15 require Carp;
141 2         276 Carp::croak("${package}::new() - Unexpected attributes passed: " . join(', ',sort @extra_properties) . "\n");
142             }
143              
144 302         608 return $self;
145             }
146              
147             ##########################################################################################
148              
149             sub eol_to_unix {
150 59     59 1 328 my $self = shift;
151              
152 59         141 my $to_unix = $self->new({
153             'EOL' => 'unix',
154             'EOF' => 'unix',
155             'FixLast' => 'unix',
156             })->fix_eol(@_);
157 59         160 return $to_unix;
158             }
159              
160             ##########################################################################################
161              
162             sub eol_to_dos {
163 59     59 1 428 my $self = shift;
164              
165 59         127 my $to_dos = $self->new({
166             'EOL' => 'dos',
167             'EOF' => 'dos',
168             'FixLast' => 'dos',
169             })->fix_eol(@_);
170 59         155 return $to_dos;
171             }
172              
173             ##########################################################################################
174              
175             sub eol_to_mac {
176 59     59 1 424 my $self = shift;
177              
178 59         132 my $to_mac = $self->new({
179             'EOL' => 'mac',
180             'EOF' => 'mac',
181             'FixLast' => 'mac',
182             })->fix_eol(@_);
183 59         153 return $to_mac;
184             }
185              
186             ##########################################################################################
187              
188             sub eol_to_network {
189 59     59 1 437 my $self = shift;
190              
191 59         121 my $to_network= $self->new({
192             'EOL' => 'network',
193             'EOF' => 'network',
194             'FixLast' => 'yes',
195             })->fix_eol(@_);
196 59         148 return $to_network;
197             }
198              
199             ##########################################################################################
200              
201             sub eol_to_crlf {
202 59     59 1 420 my $self = shift;
203              
204 59         138 my $to_crlf = $self->new({
205             'EOL' => 'crlf',
206             'EOF' => 'remove',
207             'FixLast' => 'yes',
208             })->fix_eol(@_);
209 59         149 return $to_crlf;
210             }
211              
212             ##########################################################################################
213              
214             sub fix_eol {
215 424     424 1 1056 my $self = shift;
216              
217 424 100       540 unless (1 == @_) {
218 2         9 require Carp;
219 2         3 my $package = __PACKAGE__;
220 2         111 Carp::croak("${package}::fix_eol() - Incorrect number of parameters passed. One string (only) is required.");
221             }
222              
223 422         475 my ($string) = @_;
224 422         467 my $eol_mode = $self->eol_mode;
225 422 100       526 if ($eol_mode ne 'asis') {
226 363         380 $string = $self->_eol_to_base_lf($string);
227             }
228 422         572 my $fix_last = $self->fix_last_mode;
229 422 100       536 if ($fix_last eq 'yes') {
230 421         355 my $old_eof = '';
231 421 100       578 if ($string =~ s/(\032+)$//s) { # \032 is Ctrl-Z
232 6         8 $old_eof = "\032";
233             }
234 421 100 100     812 if (($string ne '') and ($eol_mode ne 'asis')) {
235 358 100       767 if ($string !~ m/\012$/s) {
236 4         5 $string .= "\012";
237             }
238              
239             } else {
240 63 100       79 if ($eol_mode ne 'asis') {
241 4         4 $string = "\012";
242             }
243             }
244 421         567 $string .= $old_eof;
245             }
246              
247 422         537 my $eof_handling = $self->eof_mode;
248 422 100 100     560 if ($eof_handling eq 'remove') {
    100          
249 357         407 $string =~ s/\032+$//s;
250              
251             } elsif (($eof_handling eq 'add') and ($string !~ m/\032$/s)) {
252 2         3 $string .= "\032";
253             }
254              
255 422 100       525 if ($eol_mode ne 'asis') {
256 363         288 my $eol_replacement = $eol_mode;
257 363         853 $string =~ s/\012/$eol_replacement/gs;
258             }
259 422         710 return $string;
260             }
261              
262             ##########################################################################################
263              
264             sub eol_mode {
265 426     426 1 417 my $self = shift;
266 426         398 my $eol_handling = $self->eol_handling;
267              
268 426 100       563 if ($eol_handling =~ m/^literal:(.+)$/s) {
269 59         100 return $1;
270              
271             } else {
272 367         416 my $default_eol = $self->_platform_defaults($eol_handling, 'EOL');
273 367         427 return $default_eol;
274             }
275             }
276              
277             ##########################################################################################
278              
279             sub eof_mode {
280 422     422 1 373 my $self = shift;
281              
282 422         419 my $eof_handling = $self->eof_handling;
283 422         533 my $default_eof = $self->_platform_defaults($eof_handling, 'EOF');
284 422         463 return $default_eof;
285             }
286              
287             ##########################################################################################
288              
289             sub fix_last_mode {
290 422     422 1 396 my $self = shift;
291              
292 422         408 my $fix_last = $self->fix_last_handling;
293 422         530 my $fix_last_mode = $self->_platform_defaults($fix_last, 'FixLast');
294 422         488 return $fix_last_mode;
295             }
296              
297             ##########################################################################################
298              
299             sub _platform_defaults {
300 1212     1212   988 my $self = shift;
301 1212         945 my $package = __PACKAGE__;
302              
303 1212         1320 my ($platform_name, $property) = @_;
304              
305 1212         1176 $platform_name = lc ($platform_name);
306 1212         1040 $property = lc ($property);
307              
308 1212 100 100     2357 return $platform_name if (($property eq 'fixlast') and ($platform_name =~ m/^(yes|no)$/));
309 1085 100 100     2059 return $platform_name if (($property eq 'eof') and ($platform_name =~ m/^(asis|remove|add)$/));
310              
311 1017 100       1129 if ($platform_name eq 'platform') {
312 236         280 $platform_name = lc ($^O);
313             }
314              
315 1017         947 my $platform_defaults = $_Platform_Defaults{$platform_name};
316 1017 100       1152 unless (defined ($platform_defaults)) {
317 236         204 $platform_defaults = $_Platform_Defaults{'unknown'};
318             }
319 1017         919 my $property_value = $platform_defaults->{$property};
320 1017 100       1051 unless (defined ($property_value)) {
321 1         9 require Carp;
322 1         125 Carp::croak("${package}::_platform_defaults() - Unknown property of $property");
323             }
324 1016         1172 return $property_value;
325             }
326              
327             ##########################################################################################
328              
329             sub _eol_to_base_lf {
330 363     363   312 my $self = shift;
331              
332 363         378 my ($string) = @_;
333              
334             # Undef converts to ''
335 363 100       429 return '' unless (defined $string);
336              
337             # If there are not any DOS EOLs (\015 characters), return the original string
338 362 100       655 return $string unless ($string =~ m/\015/s);
339              
340             # If there is nothing except DOS EOL, convert them to \012 directly
341 330 100       407 if ($string !~ m/\012/s) {
342 24         59 $string =~ s/\015/\012/gs;
343 24         52 return $string;
344             }
345              
346             # If the EOLs are all 'singletons', do in-place cleanup of the DOS EOLs
347 306 100 100     575 if (($string !~ m/\015\012/s) and ($string !~ m/\012\015/s)) {
348 36         72 $string =~ s/\015/\012/gs;
349 36         61 return $string;
350             }
351              
352 270         959 my @eols = $string =~ m/([\012\015]+)/sg;
353 270         283 my %replacement_map = ();
354 270         326 foreach my $eol_mode (@eols) {
355 762 100       994 next if (defined $replacement_map{$eol_mode});
356 378         340 my $replace_with = $eol_mode;
357 378         885 $replace_with =~ s/(\015\012|\012\015)/\012/gs;
358 378         822 $replace_with =~ s/\015/\012/gs;
359 378         647 $replacement_map{$eol_mode} = $replace_with;
360             }
361 270         635 $string =~ s/([\012\015]+)/$replacement_map{$1}/gse;
  762         1511  
362              
363 270         704 return $string;
364             }
365              
366             ##########################################################################################
367              
368 1064     1064 1 1213 sub eol_handling { return shift->_property('eol_handling', @_); }
369 1055     1055 1 1214 sub eof_handling { return shift->_property('eof_handling', @_); }
370 1056     1056 1 1185 sub fix_last_handling { return shift->_property('fix_last_handling', @_); }
371              
372             ##########################################################################################
373             # _property('property_name' => $property_value)
374             #
375             # get/set base accessor for property values
376              
377             sub _property {
378 3176     3176   2506 my $self = shift;
379              
380 3176         2457 my $property = shift;
381              
382 3176         2444 my $package = __PACKAGE__;
383 3176 100       3705 if (0 == @_) {
    100          
384 1290         1276 my $output = $self->{$package}->{$property};
385 1290         1760 return $output;
386              
387             } elsif (1 == @_) {
388 1885         1555 my $input = shift;
389 1885         2001 $self->{$package}->{$property} = $input;
390 1885         1894 return;
391             } else {
392 1         5 die ("Bad calling parameters to ${package}::${property}()\n");
393             }
394             }
395              
396             ##########################################################################################
397              
398             1;