in reply to [NOT] How would you decode this?
I've used getc to read the byte stream and vec to test the first and second bits of the byte. Depending on the result of the tests I either just unpack an unsigned char or append one or two more getc() operations, mask off the first two bits and then either unpack() a network short (2 byte piece) or a left-padded with 8 0-bits network long (3 byte piece). I have not incorporated error checking for incomplete reads.
use strict; use warnings; use 5.010; my $mask2 = pack q{CC}, 0b00111111, 0b11111111; my $mask3 = pack q{CCC}, 0b00111111, 0b11111111, 0b11111111; my @packed = ( pack( q{C}, 0b01010101 ), pack( q{CC}, 0b10101010, 0b10101010 ), pack( q{CCC}, 0b11001100, 0b11001100, 0b11001100 ), ); my $byteStream = ( join q{}, @packed ) x 3; open my $byteStreamFH, q{<}, \ $byteStream or die $!; while ( defined( my $piece = getc( $byteStreamFH ) ) ) { unless ( vec $piece, 7, 1 ) { # 1 byte piece # say unpack q{C}, $piece; } elsif ( vec $piece, 6, 1 ) { # 3 byte piece # $piece .= getc( $byteStreamFH ) for 1 .. 2; $piece &= $mask3; say unpack q{N}, pack( q{C}, 0 ) . $piece; } else { # 2 byte piece # $piece .= getc( $byteStreamFH ); $piece &= $mask2; say unpack q{n}, $piece; } } close $byteStreamFH or die $!;
The output
85 10922 838860 85 10922 838860 85 10922 838860
I don't know how quick this would be on a large volume of data but I would imagine that a solution in C would be somewhat faster.
I hope this is of interest.
Cheers,
JohnGG
|
|---|