File Coverage

blib/lib/D64/Disk/Image/File.pm
Criterion Covered Total %
statement 55 55 100.0
branch 8 8 100.0
condition 5 9 55.5
subroutine 12 12 100.0
pod 4 4 100.0
total 84 88 95.4


line stmt bran cond sub pod time code
1             package D64::Disk::Image::File;
2              
3             =head1 NAME
4              
5             D64::Disk::Image::File - File I/O portion of Perl interface to Per Olofsson's "diskimage.c", an ANSI C library for manipulating Commodore disk images
6              
7             =head1 SYNOPSIS
8              
9             use D64::Disk::Image qw(:all);
10              
11             # Load an image from disk:
12             my $d64 = D64::Disk::Image->load_image('disk.d64');
13              
14             # Write data to file:
15             my $rawname = $d64->rawname_from_name('testfile');
16             my $prg = $d64->open($rawname, T_PRG, F_WRITE);
17             my $counter = $prg->write($buffer);
18             $prg->close();
19              
20             # Read data from file:
21             my $rawname = $d64->rawname_from_name('testfile');
22             my $prg = $d64->open($rawname, T_PRG, F_READ);
23             my ($counter, $buffer) = $prg->read();
24             $prg->close();
25              
26             # Write the image to disk:
27             $d64->free_image();
28              
29             =head1 DESCRIPTION
30              
31             Per Olofsson's "diskimage.c" is an ANSI C library for manipulating Commodore disk images. In Perl the following operations are implemented via D64::Disk::Image::File package:
32              
33             =over
34              
35             =item *
36             Open file ('$' reads directory)
37              
38             =item *
39             Read file
40              
41             =item *
42             Write file
43              
44             =item *
45             Close file
46              
47             =back
48              
49             =head1 METHODS
50              
51             =cut
52              
53 4     4   26 use bytes;
  4         7  
  4         22  
54 4     4   116 use strict;
  4         6  
  4         68  
55 4     4   16 use warnings;
  4         9  
  4         196  
56              
57 4     4   24 use constant MAXIMUM_FILE_LENGTH => &D64::Disk::Image::D81_SIZE;
  4         7  
  4         242  
58              
59             # Open mode constants:
60 4     4   25 use constant F_READ => 'rb';
  4         59  
  4         183  
61 4     4   23 use constant F_WRITE => 'wb';
  4         8  
  4         259  
62              
63 4     4   28 use base qw( Exporter );
  4         11  
  4         976  
64             our %EXPORT_TAGS = ();
65             $EXPORT_TAGS{'modes'} = [ qw(&F_READ &F_WRITE) ];
66             $EXPORT_TAGS{'all'} = [ @{$EXPORT_TAGS{'modes'}} ];
67             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
68             our @EXPORT = qw();
69              
70             our $VERSION = '0.03';
71              
72 4     4   27 use Carp qw/carp croak verbose/;
  4         20  
  4         2025  
73              
74             =head2 new
75              
76             Create new D64::Disk::Image::File object and open file on a disk image:
77              
78             my $imageFile = D64::Disk::Image::File->new($diskImage, $rawname, $fileType, $mode);
79             my $imageFile = D64::Disk::Image::File->open($diskImage, $rawname, $fileType, $mode);
80              
81             Opens a file for reading or writing. Mode should be either F_READ (for reading) or F_WRITE (for writing). If '$' is given instead of the raw filename, the directory will be read. Consult D64::Disk::Image module documentation for the list of available file types. All parameters are mandatory.
82              
83             =cut
84              
85             sub new {
86 20     20 1 36 my $this = shift;
87 20         30 my $diskImage = shift;
88 20         25 my $rawname = shift;
89 20         26 my $fileType = shift;
90 20         31 my $mode = shift;
91 20 100       47 $diskImage = $diskImage->{'DISK_IMAGE'} unless ref $diskImage eq 'DiskImagePtr';
92 20   33     54 my $class = ref($this) || $this;
93 20         422 my $self = {};
94 20         35 bless $self, $class;
95 20         101 my $imageFile = di_open($diskImage, $rawname, $fileType, $mode);
96 20         50 my $name = D64::Disk::Image->name_from_rawname($rawname);
97 20 100       475 croak "Failed to open image file '${name}' in '${mode}' mode" unless defined $imageFile;
98 17         40 $self->{'IMAGE_FILE'} = $imageFile;
99 17 100       38 $self->{'WRITE_CALLED'} = $mode eq F_READ ? 1 : 0;
100 17         46 return $self;
101             }
102              
103             *open = \&new;
104              
105             =head2 close
106              
107             Close a file (each opened file needs to be subsequently closed to avoid memory leaks):
108              
109             $imageFile->close();
110              
111             =cut
112              
113             sub close {
114 16     16 1 1900 my $self = shift;
115 16         27 my $imageFile = $self->{'IMAGE_FILE'};
116             # Make sure there is no file without any content ever created (which would
117             # result in uninitialized values of track/sector for this file in diskdir):
118 16 100       39 $self->write(chr 0x00) unless $self->{'WRITE_CALLED'};
119 16         59 di_close($imageFile);
120             }
121              
122             =head2 read
123              
124             Read data from file opened in F_READ mode:
125              
126             my ($counter, $buffer) = $imageFile->read($maxlength);
127              
128             Reads $maxlength bytes of data into the buffer. Returns the number of bytes actually read, and the buffer with succeeding bytes of data.
129              
130             =cut
131              
132             sub read {
133 3     3 1 15 my $self = shift;
134 3   66     13 my $maxlength = shift || &MAXIMUM_FILE_LENGTH;
135 3         6 my $imageFile = $self->{'IMAGE_FILE'};
136 3         1256 my ($counter, $buffer) = di_read($imageFile, $maxlength);
137 3         16 return ($counter, $buffer);
138             }
139              
140             =head2 write
141              
142             Write data to file opened in F_WRITE mode:
143              
144             my $counter = $imageFile->write($buffer, $length);
145              
146             Writes $length bytes of data from the $buffer. Returns the number of bytes actually written.
147              
148             =cut
149              
150             sub write {
151 12     12 1 219 my $self = shift;
152 12         17 my $buffer = shift;
153 12   66     49 my $length = shift || length $buffer;
154 12         21 my $imageFile = $self->{'IMAGE_FILE'};
155 12         52 my $counter = di_write($imageFile, $buffer, $length);
156 12         20 $self->{'WRITE_CALLED'} = 1;
157 12         27 return $counter;
158             }
159              
160             =head1 BUGS
161              
162             There are no known bugs at the moment. Please report any bugs or feature requests.
163              
164             =head1 EXPORT
165              
166             C exports nothing by default.
167              
168             You may request the import of open mode constants (C, and C). Both these constants can be explicitly imported from C by using it with ":modes" tag. All constants can be explicitly imported from C by using it with ":all" tag.
169              
170             =head1 SEE ALSO
171              
172             L
173              
174             =head1 AUTHOR
175              
176             Pawel Krol, Epawelkrol@cpan.orgE.
177              
178             =head1 VERSION
179              
180             Version 0.03 (2018-11-24)
181              
182             =head1 COPYRIGHT AND LICENSE
183              
184             diskimage.c is released under a slightly modified BSD license.
185              
186             Copyright (c) 2003-2006, Per Olofsson
187             All rights reserved.
188              
189             Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
190              
191             - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
192             - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
193              
194             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
195              
196             diskimage.c website: L
197              
198             =cut
199              
200             1;