Changeset 3413 for lang/perl/Archive-Lha

Show
Ignore:
Timestamp:
12/21/07 18:32:34 (12 months ago)
Author:
charsbar
Message:

lang/perl/Archive-Lha: xs -> trunk

Location:
lang/perl/Archive-Lha/trunk
Files:
3 added
7 removed
8 modified

Legend:

Unmodified
Added
Removed
  • lang/perl/Archive-Lha/trunk/Changes

    r3270 r3413  
    11Revision history for Archive-Lha 
    22 
    3 0.01 2007/12/18 
    4   - initial CodeRepos release 
     30.01 2007/12/10 
     4  - initial release 
  • lang/perl/Archive-Lha/trunk/MANIFEST

    r3270 r3413  
    11Changes 
     2Lha.h 
     3Lha.xs 
    24lib/Archive/Lha.pm 
    3 lib/Archive/Lha/Bitstream.pm 
    45lib/Archive/Lha/Constants.pm 
    5 lib/Archive/Lha/CRC.pm 
    66lib/Archive/Lha/Debug.pm 
    77lib/Archive/Lha/Decode.pm 
     
    1616lib/Archive/Lha/Header/Level2.pm 
    1717lib/Archive/Lha/Header/Utils.pm 
    18 lib/Archive/Lha/Queue.pm 
    1918lib/Archive/Lha/Stream.pm 
    2019lib/Archive/Lha/Stream/File.pm 
    2120lib/Archive/Lha/Stream/Hex.pm 
    2221lib/Archive/Lha/Stream/String.pm 
    23 lib/Archive/Lha/Table.pm 
    24 lib/Archive/Lha/TableSet.pm 
    25 lib/Archive/Lha/Tree.pm 
    2622Makefile.PL 
    2723MANIFEST                        This list of files 
     24ppport.h 
    2825README 
    2926t/00_load.t 
  • lang/perl/Archive-Lha/trunk/Makefile.PL

    r3270 r3413  
    1616    'List::Util'          => 0, 
    1717    'Log::Dispatch'       => 0, 
     18    'Test::UseAllModules' => 0, 
    1819    'Test::More'          => 0.47, 
    19     'Test::UseAllModules' => 0, 
    2020    'Time::Piece'         => 0, 
    2121  }, 
  • lang/perl/Archive-Lha/trunk/lib/Archive/Lha.pm

    r3270 r3413  
    55 
    66our $VERSION = '0.01'; 
     7 
     8require XSLoader; 
     9XSLoader::load('Archive::Lha', $VERSION); 
    710 
    8111; 
     
    2023=head1 ACKNOWLEDGMENT 
    2124 
    22 The decoding algorithm used here is based on the one of LHa for UNIX version 1.14i-ac20050924p1. Though largely modified, you may find that some parts of this perl port are still similar, or almost literal translations of the original, especially where I've not fully understood yet. 
     25The decoding (XS) part is based on the C sources of LHa for UNIX version 1.14i-ac20050924p1. Though I modified a lot not only to XSify but aslo to make it (comparatively) thread-safe and easy to understand, I'm not fair if I omit the names of the original authors/contributors. If you find this port valuable, kudos be to them. If you find something wrong, most probably that'd be my fault. 
    2326 
    24 Well, as a whole, they are different, in terms of file layout, object-orientedness and thread safety, not to mention the language used. 
     27According to the original C sources, those parts of LHa for UNIX version 1.14i-ac20050924p1 are copyrighted by Nobutaka Watazaki (1993-1995), Tsugio Okamoto (1996-2000?), and Koji Arai (2002-). I'm grateful to them, and also to all the people who involved in the development of LHa and its descendants/relatives including Masaru Oki, Yoichi Tagawa, Haruhiko Okumura, Haruyasu Yoshizaki, Kazuhiko Miki and others. 
    2528 
    26 However, I'm not fair if I omit the names of the original authors/contributors. If you find this port valuable, kudos be to them. If you find something wrong, most probably that'd be my fault. 
    27  
    28 According to the C sources, those parts of LHa for UNIX version 1.14i-ac20050924p1 are copyrighted by Nobutaka Watazaki (1993-1995), Tsugio Okamoto (1996-2000?), and Koji Arai (2002-). I'm grateful to them, and also to all the people who involved in the development of LHa and its descendants/relatives including Masaru Oki, Yoichi Tagawa, Haruhiko Okumura, Haruyasu Yoshizaki, Kazuhiko Miki and others. 
     29Other parts including headers file and perl sources are mine or of contributors to this perl port. See appropriate POD sections for details. 
    2930 
    3031=head1 SEE ALSO 
  • lang/perl/Archive-Lha/trunk/lib/Archive/Lha/Decode/Base.pm

    r3270 r3413  
    66use List::Util qw( min ); 
    77use Archive::Lha::Constants; 
    8 use Archive::Lha::Bitstream; 
    9 use Archive::Lha::Queue; 
    10 use Archive::Lha::TableSet; 
    11 use Archive::Lha::Tree; 
     8use base qw( Archive::Lha ); 
    129 
    1310sub import { 
     
    1815    no strict 'refs'; no warnings 'redefine'; 
    1916 
    20     my $dicbit = $options{dicbit}; 
     17    my $dicbit = $options{dicbit} || 13; 
    2118 
    2219    # these should be configurable, probably? 
     
    6865  my $header = $options{header}; 
    6966 
    70   my $bitstream = Archive::Lha::Bitstream->new( 
    71     callback => $options{read}, 
    72     length   => $header->{packed_size}, 
    73   ); 
    74  
    75   my $pt_table = Archive::Lha::TableSet->new( 
    76     bit => $class->PT_TABLE_BIT, length => $class->NPT 
    77   ); 
    78   my $c_table = Archive::Lha::TableSet->new( 
    79     bit => $class->C_TABLE_BIT, length => $class->NC 
    80   ); 
    81   my $tree = Archive::Lha::Tree->new( size => 2 * $class->NC - 1 ); 
    82  
    8367  my $self  = bless { 
    8468    blocksize => 0, 
    85     pt        => $pt_table, 
    86     c         => $c_table, 
    87     tree      => $tree, 
    88     bit       => $bitstream, 
     69    read      => $options{read}, 
    8970    write     => $options{write}, 
     71    packed    => $header->{packed_size}, 
    9072    original  => $header->{original_size}, 
    91     crc16     => $header->{crc16}, 
     73    crc16     => $header->{crc16} || 0, 
     74    DICSIZE   => $class->DICSIZE, 
     75    MAXMATCH  => $class->MAXMATCH, 
     76    THRESHOLD => $class->THRESHOLD, 
     77    NPT       => $class->NPT, 
     78    NP        => $class->NP, 
     79    NT        => $class->NT, 
     80    NC        => $class->NC, 
     81    PBIT      => $class->PBIT, 
     82    TBIT      => $class->TBIT, 
     83    CBIT      => $class->CBIT, 
     84    PT_TABLE_BIT  => $class->PT_TABLE_BIT, 
     85    PT_TABLE_SIZE => $class->PT_TABLE_SIZE, 
     86    C_TABLE_BIT   => $class->C_TABLE_BIT, 
     87    C_TABLE_SIZE  => $class->C_TABLE_SIZE, 
    9288  }, $class; 
    9389 
    9490  $self; 
    95 } 
    96  
    97 sub decode {  # modified from slide.c:decode 
    98   my $self = shift; 
    99  
    100   my $queue = Archive::Lha::Queue->new( 
    101     size     => $self->DICSIZE, 
    102     callback => $self->{write}, 
    103   ); 
    104   my $adjust   = ( 1 << UCHAR_BIT ) - $self->THRESHOLD; 
    105   my $total    = 0; 
    106   my $original = $self->{original}; 
    107  
    108   while ( $total < $original ) { 
    109     my $char = $self->_decode_c; 
    110     if ( $char <= UCHAR_MAX ) { 
    111       $queue->set( $char ); 
    112       $total++; 
    113     } 
    114     else { 
    115       my $length = $char - $adjust; 
    116       my $offset = $self->_decode_p + 1; 
    117  
    118       $queue->copy( $offset, $length ); 
    119       $total += $length; 
    120     } 
    121   } 
    122   $queue->output; 
    123   croak "CRC mismatch" if $queue->crc16 != $self->{crc16}; 
    124 } 
    125  
    126 sub _decode_c {  # modified from huf.c:decode_c 
    127   my $self = shift; 
    128  
    129   if ( $self->{blocksize} == 0 ) { 
    130     $self->{blocksize} = $self->bit->read( USHORT_BIT ); 
    131     $self->_read_pt( $self->NT, $self->TBIT, 3 ); 
    132     $self->_read_c; 
    133     $self->_read_pt( $self->NP, $self->PBIT, -1 ); 
    134   } 
    135   $self->{blocksize}--; 
    136  
    137   my $char = $self->c->value( $self->bit->peek( $self->c->bit ) ); 
    138  
    139   if ( $char < $self->c->length_size ) { 
    140     $self->bit->cut( $self->c->length( $char ) ); 
    141   } 
    142   else { 
    143     $self->bit->cut( $self->c->bit ); 
    144     $char = $self->tree->_follow( 
    145       from  => $char, 
    146       bits  => $self->bit->peek( USHORT_BIT ), 
    147       limit => $self->c->length_size, 
    148     ); 
    149     $self->bit->cut( $self->c->length( $char ) - $self->c->bit ); 
    150   } 
    151   return $char; 
    152 } 
    153  
    154 sub _decode_p {  # modified from huf.c:decode_p 
    155   my $self = shift; 
    156  
    157   my $pt = $self->pt->value( $self->bit->peek( $self->pt->bit ) ); 
    158  
    159   if ( $pt < $self->NP ) { 
    160     $self->bit->cut( $self->pt->length( $pt ) ); 
    161   } 
    162   else { 
    163     $self->bit->cut( $self->pt->bit ); 
    164     $pt = $self->tree->_follow( 
    165       from  => $pt, 
    166       bits  => $self->bit->peek( USHORT_BIT ), 
    167       limit => $self->NP, 
    168     ); 
    169     $self->bit->cut( $self->pt->length( $pt ) - $self->pt->bit ); 
    170   } 
    171   if ( $pt ) { 
    172     $pt = ( 1 << ( $pt - 1 ) ) + $self->bit->read( $pt - 1 ); 
    173   } 
    174   return $pt; 
    175 } 
    176  
    177 sub _read_pt {  # modified from huf.c:read_pt_len 
    178   my ($self, $nn, $nbit, $threshold) = @_; 
    179  
    180   my $n = $self->bit->read( $nbit ); 
    181   if ( $n == 0 ) { 
    182     $self->pt->fill_value( with => $self->bit->read( $nbit ) ); 
    183     $self->pt->fill_length( with => 0, to => $nn ); 
    184   } 
    185   else { 
    186     my $i = 0; 
    187     while ( $i < min( $n, $self->pt->length_size ) ) { 
    188       my $c = $self->bit->peek(3); 
    189       if ( $c == 7 ) { 
    190         my $mask = _ushort( 1 << ( ( USHORT_BIT - 1 ) - 3 ) ); 
    191         while ( $self->bit->check( $mask ) ) { 
    192           $mask >>= 1; 
    193           $c++; 
    194         } 
    195         $self->bit->cut( $c - 3 ); 
    196       } 
    197       else { 
    198         $self->bit->cut(3); 
    199       } 
    200  
    201       $self->pt->length( $i++ => $c ); 
    202       if ( $i == $threshold ) { 
    203         $c = $self->bit->read(2); 
    204         while( --$c >= 0 && $i < $self->pt->length_size ) { 
    205           $self->pt->length( $i++ => 0 ); 
    206         } 
    207       } 
    208     } 
    209     $self->pt->fill_length( with => 0, from => $i, to => $nn ); 
    210     $self->_make_table( $self->pt, $nn ); 
    211   } 
    212 } 
    213  
    214 sub _read_c {  # modified from huf.c:read_c_len 
    215   my $self = shift; 
    216  
    217   my $n = $self->bit->read( $self->CBIT ); 
    218   if ( $n == 0 ) { 
    219     $self->c->fill_value( with => $self->bit->read( $self->CBIT ) ); 
    220     $self->c->fill_length( with => 0 ); 
    221   } 
    222   else { 
    223     my $i = 0; 
    224     while ( $i < min( $n, $self->c->length_size ) ) { 
    225       my $c = $self->pt->value( $self->bit->peek( $self->pt->bit ) ); 
    226       if ( $c >= $self->NT ) { 
    227         $c = $self->tree->_follow( 
    228           from       => $c, 
    229           bits       => $self->bit->peek( USHORT_BIT ), 
    230           mask_shift => $self->pt->bit, 
    231           limit      => $self->NT, 
    232         ); 
    233       } 
    234       $self->bit->cut( $self->pt->length( $c ) ); 
    235       if ( $c <= 2 ) { 
    236         if ( $c == 0 ) { 
    237           $c = 1; 
    238         } 
    239         elsif ( $c == 1 ) { 
    240           $c = $self->bit->read(4) + 3; 
    241         } 
    242         else { 
    243           $c = $self->bit->read( $self->CBIT ) + 20; 
    244         } 
    245         while ( --$c >= 0 ) { 
    246           $self->c->length( $i++ => 0 ); 
    247         } 
    248       } 
    249       else { 
    250         $self->c->length( $i++ => $c - 2 ); 
    251       } 
    252     } 
    253     $self->c->fill_length( with => 0, from => $i ); 
    254     $self->_make_table( $self->c, $self->c->length_size ); 
    255   } 
    256 } 
    257  
    258 sub _make_table {  # modified from maketbl.c:make_table 
    259   my ($self, $table, $nchar) = @_; 
    260  
    261   my (@count, @weight, @start); 
    262  
    263   for( my $i = 1; $i <= USHORT_BIT; $i++ ) { 
    264     $count[$i]  = 0; 
    265     $weight[$i] = _ushort( 1 << ( USHORT_BIT - $i ) ); 
    266   } 
    267  
    268   for( my $i = 0; $i < $nchar; $i++ ) { 
    269     if ( $table->length( $i ) > USHORT_BIT ) { 
    270       croak "Table is broken: ".$table->stringify; 
    271     } 
    272     $count[ $table->length( $i ) ]++; 
    273   } 
    274  
    275   my $total = 0; 
    276   for( my $i = 1; $i <= USHORT_BIT; $i++ ) { 
    277     $start[$i] = $total; 
    278     $total += $weight[$i] * $count[$i]; 
    279   } 
    280  
    281   if ( $total & USHORT_MAX ) { 
    282     croak "Table is broken: ".$table->stringify; 
    283   } 
    284  
    285   my $m = USHORT_BIT - $table->bit; 
    286  
    287   for( my $i = 1; $i <= $table->bit; $i++ ) { 
    288     $start[$i]  = _ushort( $start[$i] >> $m ); 
    289     $weight[$i] = _ushort( $weight[$i] >> $m ); 
    290   } 
    291  
    292   my $j = $start[ $table->bit + 1 ] >> $m; 
    293   my $k = min( 1 << $table->bit, $table->size ); 
    294  
    295   if ( $j ) { 
    296     $table->fill_value( with => 0, from => $j, to => $k ); 
    297   } 
    298  
    299   my $avail = $nchar; 
    300   for( my $j = 0; $j < $nchar; $j++ ) { 
    301     my $k = $table->length( $j ) or next; 
    302     my $l = $start[$k] + $weight[$k]; 
    303  
    304     if ( $k <= $table->bit ) { 
    305       $l = min( $l, $table->size ); 
    306       $table->fill_value( with => $j, from => $start[$k], to => $l ); 
    307     } 
    308     else { 
    309       my $i = $start[$k]; 
    310       if ( ( $i >> $m ) > $table->size ) { 
    311         croak "Table is broken: ".$table->stringify; 
    312       } 
    313  
    314       my $p_addr = $i >> $m; 
    315       my $p_type = 'table'; 
    316       my $p      = $table->value( $p_addr ); 
    317       my $n = $k - $table->bit; 
    318       $i = _ushort( $i << $table->bit ); 
    319  
    320       while ( --$n >= 0 ) { 
    321         if ( $p == 0 ) { 
    322           $self->tree->right( $avail => 0 ); 
    323           $self->tree->left(  $avail => 0 ); 
    324           $p = $avail++; 
    325           if ( $p_type eq 'table' ) { 
    326             $table->value( $p_addr => $p ); 
    327           } 
    328           elsif ( $p_type eq 'right' ) { 
    329             $self->tree->right( $p_addr => $p ); 
    330           } 
    331           elsif ( $p_type eq 'left' ) { 
    332             $self->tree->left( $p_addr => $p ); 
    333           } 
    334         } 
    335         if ( $i >= USHORT_CENTER ) { 
    336           $p_type = 'right'; 
    337           $p_addr = $p; 
    338           $p = $self->tree->right( $p_addr ); 
    339         } 
    340         else { 
    341           $p_type = 'left'; 
    342           $p_addr = $p; 
    343           $p = $self->tree->left( $p_addr ); 
    344         } 
    345         $i = _ushort( $i << 1 ); 
    346       } 
    347       if ( $p_type eq 'table' ) { 
    348         $table->value( $p_addr => $j ); 
    349       } 
    350       elsif ( $p_type eq 'right' ) { 
    351         $self->tree->right( $p_addr => $j ); 
    352       } 
    353       elsif ( $p_type eq 'left' ) { 
    354         $self->tree->left( $p_addr => $j ); 
    355       } 
    356     } 
    357     $start[$k] = $l; 
    358   } 
    35991} 
    36092 
  • lang/perl/Archive-Lha/trunk/lib/Archive/Lha/Decode/LH0.pm

    r3270 r3413  
    44use warnings; 
    55use Carp; 
     6use bytes; 
    67use Archive::Lha::Constants; 
    7 use Archive::Lha::CRC; 
     8use Archive::Lha; 
    89 
    910sub new { 
     
    2627  my $self = shift; 
    2728 
     29  my $crc   = 0; 
    2830  my $total = 0; 
    2931  my $size  = $self->{size}; 
    30   my $crc   = Archive::Lha::CRC->new; 
    31  
    3232  while ( $total < $size ) { 
    3333    my $left = $size - $total; 
     
    3535    my $str = $self->{read}->( $length ); 
    3636    $self->{write}->( $str ); 
    37     $crc->add( $str ); 
     37    $crc = Archive::Lha::crc16( $crc, $str, length($str) ); 
    3838    $total += $length; 
    3939  } 
    40   croak "CRC mismatch" if $crc->value != $self->{crc16}; 
     40  croak "CRC mismatch" if $crc != $self->{crc16}; 
     41  return $crc; 
    4142} 
    4243 
  • lang/perl/Archive-Lha/trunk/lib/Archive/Lha/Header/Level0.pm

    r3270 r3413  
    2222  my $checksum  = ord( $bits[1] ); 
    2323  my $checksum1 = ( sum( map { ord } @bits[2..$#bits] ) ) & CHAR_MAX; 
    24   croak "Header is broken: checksum $checksum/$checksum1" 
     24  croak "Header is broken: start:$start checksum $checksum/$checksum1" 
    2525    unless $checksum == $checksum1; 
    2626 
  • lang/perl/Archive-Lha/trunk/t/20_decode.t

    r3270 r3413  
    2727      write  => sub { $decoded .= join '', @_ }, 
    2828    ); 
    29     $decoder->decode; 
     29    my $crc = $decoder->decode; 
     30    if ( $header->{crc16} ) { 
     31      ok $crc == $header->{crc16}, "CRC: $crc / $$header{crc16}"; 
     32    } 
    3033 
    3134    if ( defined $value ) {