diff --git a/lib/Subtitle/SSA.pm b/lib/Subtitle/SSA.pm index 427b5e4..362d572 100644 --- a/lib/Subtitle/SSA.pm +++ b/lib/Subtitle/SSA.pm @@ -82,7 +82,7 @@ sub parse { } my $curr = $self->{fonts}->[-1] or next; # missing 'fontname' line? - $curr->parse_uue_line($line); + $curr->add_uue_line($line); next; } # TODO: graphics section diff --git a/lib/Subtitle/SSA/File.pm b/lib/Subtitle/SSA/File.pm index 7776a62..019fd88 100644 --- a/lib/Subtitle/SSA/File.pm +++ b/lib/Subtitle/SSA/File.pm @@ -21,7 +21,7 @@ sub new { sub size { my ($self) = @_; - return length $self->{data}; + return _length_bytes($self->{data}); } ## accessors / setters @@ -67,51 +67,51 @@ sub name { ## import functions -sub load { - my ($self, $path) = @_; +sub from_binary { + my ($self, $bin) = @_; - open my $FH, '<', $path or - return $self->error("can't open file: $path -- $!"); - local $/ = undef; - $self->{data} = <$FH>; - close $FH; + return unless defined $bin and length($bin) > 0; + $self->{data} = _encode_uue($bin); return 1; } -sub parse_uue_line { +sub add_uue_line { my ($self, $line) = @_; - - # 1-char uue chunk with 6 significant bits can't hold 1 byte with 8 bits - return $self->error("bad uuencoded data (odd length)\n") - if length($line) % 4 == 1; - - # decode uue to binary form - my $bytes = _decode_uue($line); - $self->{data} .= $bytes; - - return length $bytes; + my $len = length($line); + + if ($len == 80) { + # optimization + $self->{data} .= $line; + return 60; + } elsif ($len % 4 == 1) { + # 1-char uue chunk with 6 significant bits can't hold 1 byte with 8 bits + return $self->error("bad uuencoded data (odd length)\n"); + } elsif ($len == 0) { + return 0; + } # else... + + chomp $line; + $self->{data} .= $line; + return _length_bytes($line); } ## export functions -sub binary { - my ($self, $bin) = @_; - if (defined $bin) { - $self->{data} = $bin; - } - return $self->{data}; +sub to_binary { + my ($self) = @_; + return _decode_uue($self->{data}); } -sub uue_line { +sub uue_string { my ($self) = @_; - return _encode_uue($self->{data}); + return $self->{data}; } sub uue_block { my ($self) = @_; - my $uue = $self->uue_line; + my $uue = $self->uue_string; my $cap = ($self->{type} eq 'font') ? 'fontname' : 'filename'; my $out = sprintf '%s: %s%s', $cap, $self->{name}, $self->{eol}; while (my $line = substr($uue, 0, 80, '')) { @@ -124,6 +124,14 @@ sub uue_block { ## private UUE functions +sub _length_bytes { + my ($uue) = @_; + my $len = length $uue; + my $tail = $len % 4; + my $size = int($len / 4) * 3; + return $size + int(($tail * 6) / 8); +} + sub _decode_uue { my ($uue) = @_; my $bytes = ''; diff --git a/t/format-ssa-file.t b/t/format-ssa-file.t index d4cf04c..cb665a4 100644 --- a/t/format-ssa-file.t +++ b/t/format-ssa-file.t @@ -17,15 +17,15 @@ sub random_data { my $file = Subtitle::SSA::File->new; is(ref $file, 'Subtitle::SSA::File'); -can_ok($file, qw(new error size type name parse_uue_line binary uue_line uue_block)); +can_ok($file, qw(new error size type name from_binary add_uue_line to_binary uue_string uue_block)); undef $file; for (my $i = 0; $i < 15; $i++) { my $bin = random_data(); $file = Subtitle::SSA::File->new; - $file->binary($bin); + $file->from_binary($bin); is($file->size => length $bin); - my $uue = $file->uue_line; + my $uue = $file->uue_string; isnt($uue, ''); ok(length($uue) % 4 != 1); my $invalid = 0;