File Coverage

blib/lib/Games/ScottAdams/File.pm
Criterion Covered Total %
statement 27 56 48.2
branch 8 16 50.0
condition 0 4 0.0
subroutine 5 11 45.4
pod 0 8 0.0
total 40 95 42.1


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         43  
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   1204 use IO::File;
  1         15634  
  1         1065  
16              
17              
18             sub new {
19 5     5 0 8 my $class = shift();
20 5         7 my($filename) = @_;
21              
22 5 50       41 my $f = new IO::File("<$filename")
23             or return undef;
24              
25 5         492 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 873 my $this = shift();
37 676         734 my($trim) = @_;
38              
39 676         701 my $line = pop @{ $this->{pushback} };
  676         1268  
40 847 100       1796 if (!defined $line) {
41 666         976 AGAIN:
42             $this->{linenumber}++;
43 666         16625 $line = $this->{f}->getline();
44 666 100       33476 return undef if !defined $line;
45             }
46              
47 841 50       1564 if ($trim) {
48 841         1331 $line =~ s/#.*//;
49 841         2589 $line =~ s/\s+$//;
50 841 100       7822 goto AGAIN if $line =~ /^$/;
51             }
52              
53 670         2432 return $line;
54             }
55              
56              
57             sub ungetline {
58 181     181 0 220 my $this = shift();
59 181         226 my($line) = @_;
60              
61 181         188 push @{ $this->{pushback} }, $line;
  181         572  
62             }
63              
64              
65             # Calls to getint() and getstring() may be freely intermixed, but
66             # won't play nice if mixed with getline() and ungetline() calls.
67              
68             sub getint {
69 0     0 0   my $this = shift();
70 0           $this->_refresh();
71 0 0         die "getint($this) on non-int buffer '" . $this->{buf} . "'"
72             if $this->{buf} !~ /^\d/;
73              
74 0           $this->{buf} =~ s/(\d+)//;
75 0           return $1;
76             }
77              
78             sub getstring {
79 0     0 0   my $this = shift();
80 0           $this->_refresh();
81              
82 0 0         $this->{buf} =~ s/^[""]//
83             or die "getstring($this) on non-string buffer '" . $this->{buf} . "'";
84              
85 0           my $string = "";
86 0           while ($this->{buf} !~ /[""]/) {
87 0           $string .= $this->{buf};
88 0           $this->{buf} = $this->getline();
89             }
90              
91 0 0         $this->{buf} =~ s/^(.*?)[""]//
92             or die "can't happen";
93              
94 0           $string .= $1;
95 0           $string =~ s/[``"]/"/g;
96 0           return $string;
97             }
98              
99             # PRIVATE to getint() and getstring()
100             sub _refresh {
101 0     0     my $this = shift();
102 0           while ($this->{buf} =~ /^\s*$/) {
103 0           $this->{buf} = $this->getline();
104             }
105 0           $this->{buf} =~ s/^\s*//;
106             }
107              
108              
109             sub warn {
110 0     0 0   my $this = shift();
111              
112 0           print STDERR $this->{filename}, ':', $this->{linenumber}, ': ',
113             'WARNING: ', @_, "\n";
114             }
115              
116              
117             sub fatal {
118 0     0 0   my $this = shift();
119              
120 0   0       my $filename = $this->{filename} || '[unknown]';
121 0   0       my $linenumber = $this->{linenumber} || '[unknown]';
122 0           print STDERR $filename, ':', $linenumber, ': ERROR: ', @_, "\n";
123 0           exit 1;
124             }
125              
126              
127             sub close {
128 0     0 0   my $this = shift();
129              
130 0           $this->{f}->close();
131             }
132              
133              
134             1;