File Coverage

blib/lib/Games/ScottAdams/File.pm
Criterion Covered Total %
statement 29 58 50.0
branch 8 16 50.0
condition 0 4 0.0
subroutine 5 11 45.4
pod 0 8 0.0
total 42 97 43.3


line stmt bran cond sub pod time code
1             # $Id: File.pm,v 1.3 2006-11-03 20:59:19 mike Exp $
2              
3             # File.pm - a cleverer IO::File-alike that does pushback
4              
5             package Games::ScottAdams::File;
6 1     1   7 use strict;
  1         3  
  1         38  
7              
8             # This module simply implements a slightly cleverer IO::File-alike
9             # that remembers the filename, maintains a notion of the current line
10             # number (useful for diagnostics) and can maintain an arbitrary number
11             # of pushback lines. It clearly has wider applicability outside of
12             # the Scott Adams module and should probably not be a
13             # Games::ScottAdams class.
14              
15 1     1   592 use IO::File;
  1         10770  
  1         1308  
16              
17              
18             sub new {
19 5     5 0 9 my $class = shift();
20 5         11 my($filename) = @_;
21              
22 5 50       37 my $f = new IO::File("<$filename")
23             or return undef;
24              
25 5         599 return bless {
26             f => $f,
27             filename => $filename,
28             linenumber => 0,
29             pushback => [],
30             buf => "", # for getint() and getstring() only
31             }, $class;
32             }
33              
34              
35             sub getline {
36 676     676 0 1125 my $this = shift();
37 676         1261 my($trim) = @_;
38              
39 676         1009 my $line = pop @{ $this->{pushback} };
  676         1336  
40             AGAIN:
41 847 100       2021 if (!defined $line) {
42 666         1128 $this->{linenumber}++;
43 666         2472 $line = $this->{f}->getline();
44 666 100       1490 return undef if !defined $line;
45             }
46              
47 841 50       1766 if ($trim) {
48 841         1647 $line =~ s/#.*//;
49 841         2755 $line =~ s/\s+$//;
50 841 100       2272 if ($line =~ /^$/) {
51 171         308 undef $line;
52 171         597 goto AGAIN;
53             }
54             }
55              
56 670         2140 return $line;
57             }
58              
59              
60             sub ungetline {
61 181     181 0 323 my $this = shift();
62 181         364 my($line) = @_;
63              
64 181         285 push @{ $this->{pushback} }, $line;
  181         530  
65             }
66              
67              
68             # Calls to getint() and getstring() may be freely intermixed, but
69             # won't play nice if mixed with getline() and ungetline() calls.
70              
71             sub getint {
72 0     0 0   my $this = shift();
73 0           $this->_refresh();
74             die "getint($this) on non-int buffer '" . $this->{buf} . "'"
75 0 0         if $this->{buf} !~ /^\d/;
76              
77 0           $this->{buf} =~ s/(\d+)//;
78 0           return $1;
79             }
80              
81             sub getstring {
82 0     0 0   my $this = shift();
83 0           $this->_refresh();
84              
85             $this->{buf} =~ s/^[""]//
86 0 0         or die "getstring($this) on non-string buffer '" . $this->{buf} . "'";
87              
88 0           my $string = "";
89 0           while ($this->{buf} !~ /[""]/) {
90 0           $string .= $this->{buf};
91 0           $this->{buf} = $this->getline();
92             }
93              
94 0 0         $this->{buf} =~ s/^(.*?)[""]//
95             or die "can't happen";
96              
97 0           $string .= $1;
98 0           $string =~ s/[``"]/"/g;
99 0           return $string;
100             }
101              
102             # PRIVATE to getint() and getstring()
103             sub _refresh {
104 0     0     my $this = shift();
105 0           while ($this->{buf} =~ /^\s*$/) {
106 0           $this->{buf} = $this->getline();
107             }
108 0           $this->{buf} =~ s/^\s*//;
109             }
110              
111              
112             sub warn {
113 0     0 0   my $this = shift();
114              
115 0           print STDERR $this->{filename}, ':', $this->{linenumber}, ': ',
116             'WARNING: ', @_, "\n";
117             }
118              
119              
120             sub fatal {
121 0     0 0   my $this = shift();
122              
123 0   0       my $filename = $this->{filename} || '[unknown]';
124 0   0       my $linenumber = $this->{linenumber} || '[unknown]';
125 0           print STDERR $filename, ':', $linenumber, ': ERROR: ', @_, "\n";
126 0           exit 1;
127             }
128              
129              
130             sub close {
131 0     0 0   my $this = shift();
132              
133 0           $this->{f}->close();
134             }
135              
136              
137             1;