File Coverage

blib/lib/Geo/GeoNames/File.pm
Criterion Covered Total %
statement 37 39 94.8
branch 12 16 75.0
condition 5 6 83.3
subroutine 7 7 100.0
pod 3 3 100.0
total 64 71 90.1


line stmt bran cond sub pod time code
1             package Geo::GeoNames::File;
2              
3             =head1 NAME
4              
5             Geo::GeoNames::File - Perl module for handling GeoNames.org data files
6              
7             =head1 SYNOPSIS
8              
9             use Geo::GeoNames::File;
10              
11             my $file = Geo::GeoNames::File->open( qw/US.txt GB.txt/ );
12              
13             while( my $rec = $file->next() )
14             {
15             print $rec->name . "\n";
16             }
17              
18             $file->close();
19              
20             =head1 DESCRIPTION
21              
22             Provides a Perl extention for handling GeoNames.org data files. You may
23             use this module to load GeoNames.org records from several seperate files.
24              
25             =head1 AUTHOR
26              
27             Xiangrui Meng
28              
29             =head1 COPYRIGHT
30              
31             Copyright (C) 2009 by Xiangrui Meng
32              
33             This library is free software; you can redistribute it and/or modify
34             it under the same terms as Perl itself, either Perl version 5.8.8 or,
35             at your option, any later version of Perl 5 you may have available.
36              
37             =cut
38              
39 2     2   32205 use 5.008007;
  2         9  
  2         161  
40 2     2   13 use strict;
  2         3  
  2         153  
41 2     2   11 use warnings;
  2         4  
  2         67  
42              
43 2     2   12 use Carp ();
  2         2  
  2         817  
44              
45             require Geo::GeoNames::Record;
46              
47             =over
48              
49             =item open()
50              
51             Open files.
52              
53             my $file = Geo::GeoNames::File->open( @geonames_filenames );
54              
55             =cut
56              
57             sub open
58             {
59 2     2 1 26 my $class = shift;
60 2         6 my @filenames = @_;
61              
62 2         11 my $self = {
63             filenames => \@filenames,
64             cur_filename => undef,
65             cur_fh => undef,
66             };
67              
68 2         7 bless $self, $class;
69              
70 2         7 return $self;
71             }
72              
73             =item close()
74              
75             Close open file handles.
76              
77             =cut
78              
79             sub close
80             {
81 2     2 1 637 my $self = shift;
82              
83 2 50       104 if( $self->{cur_fh} )
84             {
85 0         0 CORE::close $self->{cur_fh};
86             }
87             }
88              
89             =item next()
90              
91             my $record = $batch->next();
92              
93             Return the next record in the file as a Geo::GeoNames::Record object. If a
94             filter function is supplied, it will return the next filtered record.
95              
96             sub pop_gt_100000
97             {
98             return (shift->population > 100000);
99             }
100              
101             my $record = $file->next( \&pop_gt_100000 );
102              
103             =cut
104              
105             sub next
106             {
107 20     20 1 712 my ( $self, $filter ) = @_;
108            
109 20 50 66     89 if ( $filter and ref($filter) ne 'CODE' )
110             {
111 0         0 Carp::croak( "filter function must be a subroutine reference." );
112             }
113            
114 20 100       60 if( $self->{cur_fh} ) # if cur_fh is active
115             {
116 15         19 while(1)
117             {
118 33 100       191 if( eof($self->{cur_fh}) )
119             {
120 3         68 CORE::close $self->{cur_fh};
121 3         8 $self->{cur_fh} = undef;
122            
123 3         16 return $self->next($filter);
124             }
125             else
126             {
127 30         42 my $fh = $self->{cur_fh};
128 30         152 my $line = <$fh>;
129            
130 30 50       94 next if $line =~ /^\s*#/;
131              
132 30         114 my $rec = Geo::GeoNames::Record->new( $line );
133              
134 30 100 100     90 next if( $filter and !($filter->($rec)) );
135              
136 12         77 return $rec;
137             }
138             }
139             }
140             else # open next file
141             {
142 5 100       7 $self->{cur_filename} = shift @{$self->{filenames}}
  5         38  
143             or return;
144            
145 3 50       146 CORE::open( $self->{cur_fh}, "<:utf8", $self->{cur_filename} )
146             or Carp::croak( "Couldn't open $self->{cur_filename}!" );
147            
148 3         19 return $self->next($filter);
149             }
150             }
151              
152             =back
153              
154             =cut
155              
156             1;
157             __END__