1package MaxMind::DB::Reader::Role::Sysreader; 2 3use strict; 4use warnings; 5use namespace::autoclean; 6use autodie; 7 8our $VERSION = '1.000014'; 9 10use Carp qw( confess ); 11use MaxMind::DB::Types qw( FileHandle Int ); 12 13use Moo::Role; 14 15has data_source => ( 16 is => 'ro', 17 isa => FileHandle, 18 lazy => 1, 19 builder => '_build_data_source', 20); 21 22has _data_source_size => ( 23 is => 'ro', 24 isa => Int, 25 lazy => 1, 26 builder => '_build_data_source_size', 27); 28 29## no critic (Subroutines::ProhibitUnusedPrivateSubroutines) 30sub _read { 31 my $self = shift; 32 my $buffer = shift; 33 my $offset = shift; 34 my $wanted_size = shift; 35 my $seek_from_end = shift; 36 37 my $source = $self->data_source; 38 seek $source, $offset, $seek_from_end ? 2 : 0; 39 40 my $read_offset = 0; 41 while (1) { 42 my $read_size = read( 43 $source, 44 ${$buffer}, 45 $wanted_size, 46 $read_offset, 47 ); 48 49 confess $! unless defined $read_size; 50 51 # This error message doesn't provide much context, but it should only 52 # be thrown because of a fundamental logic error in the reader code, 53 # _or_ because the writer generated a database with broken pointers 54 # and/or broken data elements. 55 confess 'Attempted to read past the end of a file/memory buffer' 56 if $read_size == 0; 57 58 return if $wanted_size == $read_size; 59 60 $wanted_size -= $read_size; 61 $read_offset += $read_size; 62 } 63 64 return; 65} 66## use critic 67 68sub _build_data_source { 69 my $class = ref shift; 70 71 die 72 "You must provide a data_source parameter to the constructor for $class"; 73} 74 75sub _build_data_source_size { 76 my $self = shift; 77 78 my @stat = stat( $self->data_source ) or die $!; 79 return $stat[7]; 80} 81 821; 83