File-Sip

 view release on metacpan or  search on metacpan

lib/File/Sip.pm  view on Meta::CPAN

package File::Sip;

#ABSTRACT: file parser intended for big files that don't fit into main memory.


use Moo;
use Carp 'croak';
use IO::File;
use Encode qw(decode);
use feature ':5.10';


has path => (
    is       => 'ro',
    required => 1,
);


has line_separator => (
    is      => 'ro',
    default => sub {qw/(\015\012|\015|\012)/},
);


has is_utf8 => (
    is      => 'ro',
    default => sub {1},
);


# internal cursor for iterations
has _read_line_position => (
    is      => 'rw',
    default => sub {0},
);

sub read_line {
    my ( $self, $line_number ) = @_;

    $line_number //= $self->_read_line_position;
    my $fh         = $self->_fh;
    my $line_index = $self->index->[$line_number];
    return if !defined $line_index;

    my $previous_line_index =
      ( $line_number == 0 ) ? 0 : $self->index->[ $line_number - 1 ];

    my $line;
    seek( $fh, $previous_line_index, 0 );
    read( $fh, $line, $line_index - $previous_line_index );

    $self->_read_line_position( $line_number + 1 ) if @_ == 1;

    return decode( "utf8", $line ) if defined $line && $self->is_utf8;
    return $line;
}

# file handle return by IO::File
has _fh => (
    is      => 'ro',
    lazy    => 1,
    default => sub {
        my ($self) = @_;
        my $open_file_param = "<:crlf";
        IO::File->new( $self->path, $open_file_param )
          or croak "Failed to open file '" . $self->path . "' : '$!'";
    }
);

# File stat array
has _stat => (
    is => 'lazy',
);

sub _build__stat {
    my ($self) = @_;
    my @stat = stat( $self->_fh );
    return \@stat;
}


has index => (
    is      => 'rw',
    lazy    => 1,
    builder => 1,
);

sub _build_index {
    my ($self) = @_;
    my $index = [];



( run in 0.785 second using v1.01-cache-2.11-cpan-71847e10f99 )