File Coverage

blib/lib/App/Timestamper/Log/Process.pm
Criterion Covered Total %
statement 109 117 93.1
branch 20 34 58.8
condition 5 11 45.4
subroutine 15 15 100.0
pod 2 2 100.0
total 151 179 84.3


line stmt bran cond sub pod time code
1             package App::Timestamper::Log::Process;
2             $App::Timestamper::Log::Process::VERSION = '0.2.0';
3 4     4   239311 use 5.014;
  4         22  
4 4     4   20 use strict;
  4         7  
  4         109  
5 4     4   19 use warnings;
  4         7  
  4         234  
6 4     4   576 use autodie;
  4         13668  
  4         24  
7              
8 4     4   22589 use bigint;
  4         18414  
  4         19  
9              
10 4     4   355823 use Carp ();
  4         17  
  4         92  
11 4     4   2833 use File::ReadBackwards ();
  4         14054  
  4         166  
12 4     4   3471 use Getopt::Long qw( GetOptionsFromArray );
  4         60664  
  4         23  
13              
14             # use parent qw(ParentClass);
15              
16             sub _argv
17             {
18 9     9   17 my $self = shift;
19              
20 9 100       19 if (@_)
21             {
22 3         22 $self->{_argv} = shift;
23             }
24              
25 9         17 return $self->{_argv};
26             }
27              
28             sub new
29             {
30 3     3 1 10 my $class = shift;
31              
32 3         9 my $self = bless {}, $class;
33              
34 3         20 $self->_init(@_);
35              
36 3         16 return $self;
37             }
38              
39             sub _init
40             {
41 3     3   8 my ( $self, $args ) = @_;
42 3   50     31 $self->_argv( $args->{argv} // ( die "no argv key" ) );
43              
44 3         7 return;
45             }
46              
47             my $NUM_DIGITS = 16;
48             my $LOW_BASE = 10;
49             my $HIGH_BASE = 1;
50             foreach my $e ( 1 .. $NUM_DIGITS )
51             {
52             $HIGH_BASE *= $LOW_BASE;
53             }
54             my $OUT_NUM_DIGITS = 8;
55             my $TO_OUT_BASE = 1;
56             foreach my $e ( 1 .. ( $NUM_DIGITS - $OUT_NUM_DIGITS ) )
57             {
58             $TO_OUT_BASE *= $LOW_BASE;
59             }
60              
61             sub run
62             {
63 3     3 1 8 my ( $self, ) = @_;
64              
65 3         8 my $argv = $self->_argv();
66              
67 3         8 my $mode = shift(@$argv);
68              
69 3 100 66     22 if ( ( $mode eq "from_start" ) or ( $mode eq "from-start" ) )
    50          
70             {
71 1         5 return $self->_mode_from_start();
72             }
73             elsif ( ( $mode eq "time" ) )
74             {
75 2         12 return $self->_mode_time();
76             }
77             else
78             {
79 0         0 Carp::confess("Unknown mode '$mode'!");
80             }
81              
82 0         0 return;
83             }
84              
85             sub _calc_ticks_and_data_str
86             {
87 40     40   97 my ( $self, $line ) = @_;
88 40         92 chomp $line;
89 40 50       324 if ( my ( $seconds, $dotdigits, $data_str ) =
90             ( $line =~ m#\A([0-9]+)((?:\.(?:[0-9]){0,16})?)\t([^\n]*\z)#ms ) )
91             {
92 40         246 my $ticks = $seconds * $HIGH_BASE;
93 40 50       10733 if ( $dotdigits =~ s#\A\.##ms )
94             {
95 40         110 $dotdigits .=
96             scalar( "0" x ( $NUM_DIGITS - length($dotdigits) ) );
97 40         10410 $ticks += ( 0 + $dotdigits );
98             }
99 40         11078 return ( $ticks, $data_str );
100             }
101             else
102             {
103 0         0 die "The line is formatted wrong";
104             }
105             }
106              
107             sub _mode_from_start
108             {
109 1     1   2 my ( $self, ) = @_;
110              
111 1         2 my $argv = $self->_argv();
112 1         2 my $output_fn;
113 1 50       5 my $ret = GetOptionsFromArray( $argv, "output|o=s" => ( \$output_fn ), )
114             or Carp::confess($!);
115 1         579 my $input_fn = shift(@$argv);
116 1 50       4 if ( not defined($input_fn) )
117             {
118 0         0 die "Must specify an input file-path!";
119             }
120 1 50       3 if (@$argv)
121             {
122 0         0 die "Leftover command-line arguments after the input filename";
123             }
124              
125 1   33     5 my $USE_STDOUT = ( not( defined($output_fn) and ( $output_fn ne "-" ) ) );
126              
127 1         3 my $out;
128 1 50       2 if ($USE_STDOUT)
129             {
130             ## no critic
131 0         0 open $out, ">&STDOUT";
132             ## use critic
133             }
134             else
135             {
136 1         5 open $out, ">", $output_fn;
137             }
138 1         1536 open my $in, "<", $input_fn;
139 1         86 my $start;
140              
141 1         34 while ( my $line = <$in> )
142             {
143 34         9289 chomp $line;
144 34         96 my ( $ticks, $data_str ) = $self->_calc_ticks_and_data_str($line);
145 34 100       87 if ( not defined($start) )
146             {
147 1         2 $start = $ticks;
148             }
149 34         70 my $distance = $ticks - $start;
150 34         4122 my $dist_seconds = $distance / $HIGH_BASE;
151 34         7521 my $dist_dot = $distance % $HIGH_BASE;
152 34         5612 $dist_dot /= $TO_OUT_BASE;
153 34         5431 $out->printf(
154             "%d\.%0*d\t%s\n", $dist_seconds, $OUT_NUM_DIGITS,
155             $dist_dot, $data_str
156             );
157             }
158              
159 1         90 close($in);
160 1 50       823 if ( not $USE_STDOUT )
161             {
162 1         3 close($out);
163             }
164              
165 1         0 return;
166             }
167              
168             sub _mode_time
169             {
170 2     2   7 my ( $self, ) = @_;
171              
172 2         7 my $argv = $self->_argv();
173 2         4 my $output_fn;
174 2 50       12 my $ret = GetOptionsFromArray( $argv, "output|o=s" => ( \$output_fn ), )
175             or Carp::confess($!);
176 2   33     1584 my $USE_STDOUT = ( not( defined($output_fn) and ( $output_fn ne "-" ) ) );
177              
178 2         4 my $out;
179 2 50       9 if ($USE_STDOUT)
180             {
181             ## no critic
182 0         0 open $out, ">&STDOUT";
183             ## use critic
184             }
185             else
186             {
187 2         14 open $out, ">", $output_fn;
188             }
189 2         4036 while (@$argv)
190             {
191 3         5925 my $input_fn = shift(@$argv);
192 3 50       11 if ( not defined($input_fn) )
193             {
194 0         0 die "Must specify an input file-path!";
195             }
196              
197 3         13 open my $in, "<", $input_fn;
198 3         320 my $start;
199              
200             {
201 3         7 my $line = <$in>;
  3         118  
202 3         26 my ( $ticks, $data_str ) = $self->_calc_ticks_and_data_str($line);
203 3 50       12 die if ( defined($start) );
204 3         7 $start = $ticks;
205             }
206              
207 3         13 close($in);
208              
209 3         1926 my $end_ticks;
210             {
211 3 50       5 my $bw_in = File::ReadBackwards->new($input_fn)
  3         28  
212             or Carp::confess("can't open $input_fn backwards $!");
213 3         321 my $line = $bw_in->readline();
214 3         313 $bw_in->close();
215 3         71 my ( $ticks, $data_str ) = $self->_calc_ticks_and_data_str($line);
216 3         23 $end_ticks = $ticks;
217             }
218 3         10 my $distance = $end_ticks - $start;
219 3         427 my $dist_seconds = $distance / $HIGH_BASE;
220 3         1000 my $dist_dot = $distance % $HIGH_BASE;
221 3         678 $dist_dot /= $TO_OUT_BASE;
222 3         746 $out->printf(
223             "%d\.%0*d\t%s\n", $dist_seconds, $OUT_NUM_DIGITS,
224             $dist_dot, $input_fn,
225             );
226             }
227              
228 2 50       10013 if ( not $USE_STDOUT )
229             {
230 2         10 close($out);
231             }
232              
233 2           return;
234             }
235              
236             1;
237              
238             __END__