Thursday, February 11, 2016

Perl6: classes and working with binary data

ROOM FOR IMPROVEMENT: It would probably be better if the class defined below implemented the Buf "role".  That way, code that used it could (for example) call .list and .elems directly on the class... which I think would be a very nice way to open up the class.  Or is that TOO open?  Meh, I think people who hack on Commodore 1541 diskette images should be implicitly trusted.

class Image {
    has Str $.sourcefile is rw;  # accessors auto-generated
    has Buf $!buffer;            # private, no accessors

    has $!hdr = (17 * 21) * 256; # byte offset
   
    method load() {
       return "no sourcefile specified" unless $.sourcefile;
       

       # read in a binary file
       my $fh = open( $.sourcefile, :r, :bin );
       $!buffer = $fh.slurp-rest(:bin);
       return "$.sourcefile loaded";

     
       # (oops - forgot to close the file)
    }
   

    method size()  { $!buffer.elems }
 


    # Each of these methods return "Buf": a class used
    # for dealing with binary data buffers.

    method label() { $!buffer.subbuf($!hdr + 143, 16) }
    method hdr()   { $!buffer.subbuf($!hdr, 256) }   
    method dir( Int $index ) {
        my $offset = $!hdr + 256 + $index * 32;
        return $!buffer.subbuf($offset+2, 30);
    }
}

my Image $test = Image.new( sourcefile => "mule.d64" );
say $test.load();
say $test.size(), " bytes read";

my $hdr   = $test.hdr();  
my $label = $test.label();

print "Label: ";
for $label.list -> $val {
   if 31 < $val < 92 { print chr($val) }
   else { print '.' }  
}
print "\n";

my $blob  = $test.dir(1); # (actually the 2nd entry)

for $blob.list -> $val {
   if 31 < $val < 92 { print chr($val) }
   else { print '.' }  
}


% perl6 Image.p6
mule.d64 loaded
174848 bytes read
Label: .M.U.L.E........
...MULE.2.....................


No comments:

Post a Comment