File Coverage

lib/Sisimai/Mail/Mbox.pm
Criterion Covered Total %
statement 47 47 100.0
branch 13 20 65.0
condition 6 7 85.7
subroutine 8 8 100.0
pod 2 2 100.0
total 76 84 90.4


line stmt bran cond sub pod time code
1             package Sisimai::Mail::Mbox;
2 86     86   127881 use v5.26;
  86         324  
3 86     86   528 use strict;
  86         220  
  86         3019  
4 86     86   437 use warnings;
  86         210  
  86         5945  
5 86     86   572 use File::Basename qw(basename dirname);
  86         188  
  86         10815  
6 86     86   54461 use IO::File;
  86         845604  
  86         15302  
7             use Class::Accessor::Lite (
8 86         1074 'new' => 0,
9             'ro' => [
10             'dir', # [String] Directory name of the mbox
11             'file', # [String] File name of the mbox
12             'path', # [String] Path to mbox
13             'size', # [Integer] File size of the mbox
14             ],
15             'rw' => [
16             'offset', # [Integer] Offset position for seeking
17             'handle', # [IO::File] File handle
18             ]
19 86     86   1470 );
  86         1749  
20              
21             sub new {
22             # Constructor of Sisimai::Mail::Mbox
23             # @param [String] argv1 Path to mbox
24             # @return [Sisimai::Mail::Mbox] Object
25             # [Undef] is not a file or does not exist
26 739     739 1 247166 my $class = shift;
27 739 50 100     3112 my $argv1 = shift // return undef; return undef unless -f $argv1;
  738         23270  
28 738         3381 my $param = {'offset' => 0};
29              
30 738         56885 $param->{'dir'} = File::Basename::dirname $argv1;
31 738         2714 $param->{'path'} = $argv1;
32 738         16174 $param->{'size'} = -s $argv1;
33 738         27843 $param->{'file'} = File::Basename::basename $argv1;
34 738 50       9600 $param->{'handle'} = ref $argv1 ? $argv1 : IO::File->new($argv1, 'r');
35 738         130483 binmode $param->{'handle'};
36              
37 738         6466 return bless($param, __PACKAGE__);
38             }
39              
40             sub read {
41             # Mbox reader, works as an iterator.
42             # @return [String] Contents of mbox
43 1732 50   1732 1 3668157 my $self = shift; return "" unless defined $self->{'path'};
  1732         8140  
44 1732   50     6524 my $seekoffset = $self->{'offset'} // 0;
45 1732         4130 my $filehandle = $self->{'handle'};
46 1732         3407 my $readbuffer = '';
47              
48 1732 50       6163 unless( ref $self->{'path'} ) {
49             # "path" is not IO::File object
50 1732 50       52934 return "" unless -f $self->{'path'};
51 1732 50       216748 return "" unless -T $self->{'path'};
52             }
53 1732 100       14627 return "" unless $self->{'offset'} < $self->{'size'};
54              
55 996         2384 eval {
56 996 50       3182 $seekoffset = 0 if $seekoffset < 0;
57 996         6704 seek($filehandle, $seekoffset, 0);
58              
59 996         16372 while( my $r = <$filehandle> ) {
60             # Read the UNIX mbox file from 'From ' to the next 'From '
61 93083 100 100     245576 last if( $readbuffer && substr($r, 0, 5) eq 'From ' );
62 92824         198297 $readbuffer .= $r;
63             }
64 996         2613 $seekoffset += length $readbuffer;
65 996         3971 $self->{'offset'} = $seekoffset;
66 996 100       7290 $filehandle->close unless $seekoffset < $self->{'size'};
67             };
68 996         23241 return $readbuffer;
69             }
70              
71             1;
72             __END__