То, что у вас есть, - это кодировка переменной длины. Длина кодируется с использованием формы значения часового: для каждого байта кодированного номера, кроме последнего, установлен старший бит. Остальные биты образуют кодирование числа с двумя дополнительными числами в порядке байтов с небольшим окончанием.
0xxxxxxx ⇒ 0xxxxxxx
1xxxxxxx 0yyyyyyy ⇒ 00yyyyyy yxxxxxxx
1xxxxxxx 1yyyyyyy 0zzzzzzz ⇒ 000zzzzz zzyyyyyy yxxxxxxx
etc
Для декодирования потока можно использовать следующее:
use strict;
use warnings;
use feature qw( say );
sub extract_first_num {
$_[0] =~ s/^([\x80-\xFF]*[\x00-\x7F])//
or return;
my $encoded_num = $1;
my $num = 0;
for (reverse unpack 'C*', $encoded_num) {
$num = ( $num << 7 ) | ( $_ & 0x7F );
}
return $num;
}
my $stream_buf = "\x10\x33\xA4\x01\x84\x03\xBA\x04\x91\x05\x81\x08\x9C\x83\x0F";
while ( my ($num) = extract_first_num($stream_buf) ) {
say $num;
}
die("Bad data") if length($stream_buf);
Выход:
16
51
164
388
570
657
1025
246172