Perl:将int打包成任意长度的字节串
Perl: pack int to arbitrary length byte string
我想在 N 位容器中编码数字并在 UDP 数据包中发送它们。接收者将知道 N,并且接收者将从恰好 N 位中获取一个数字。(N <= 64)
有些想法是这样的:
sub to56BIT {
return pack("??", shift);
}
sub to24BIT {
return pack("??", shift);
}
my $n = 7;
to24BIT($n);
接收方:
int n = Get_val24(byte_stream, offset);
有没有办法在 Perl 中做到这一点?
我认为解决方案可能是:
sub packIntN {
my $int = shift;
my $length = shift;
return pack("B" . $length, substr(unpack("B64", pack("Q>", $int)), 64 - $length));
}
但也许还有更优雅的方式。
Input/Output 示例:
我们有一个脚本 test.pl:
use strict;
use warnings;
sub to24BIT {
#???
}
my $n = 7;
print to24BIT($n);
我想要这个:
./test.pl | hexdump -C
00000000 00 00 07 |...|
00000003
另一个脚本test2.pl:
use strict;
use warnings;
sub to40BIT {
#???
}
my $n = 7;
print to40BIT($n);
我想要这个:
./test.pl | hexdump -C
00000000 00 00 00 00 07 |.....|
00000005
请记住,您将永远拥有一个完整的
字节数,我最终得到
substr(pack("Q>",$n<<(64-$len)),0,($len+7)/8);
和
unpack("Q>",$s.(0 x 8)) >> (64-$len);
如本例所试:
#!/usr/bin/perl
$len = 40;
$n = 7;
$s = substr(pack("Q>",$n<<(64-$len)),0,($len+7)/8);
open(PIPE,"| hexdump -C");
print PIPE $s;
close PIPE;
$v = unpack("Q>",$s.(0 x 8)) >> (64-$len);
printf "%d\n",$v;
N 是否总是 8 的整数因子(8、16、24、32、40、48、56、64 之一)?如果是这样,为了速度,我建议为每种尺寸编写一个打包器,并使用调度 table 找到合适的打包器。
sub pack_8bit { pack('C', $_[0]) }
sub pack_16bit { pack('S>', $_[0]) }
sub pack_24bit { substr(pack('L>', $_[0]), 1) }
sub pack_32bit { pack('L>', $_[0]) }
sub pack_40bit { substr(pack('Q>', $_[0]), 3) }
sub pack_48bit { substr(pack('Q>', $_[0]), 2) }
sub pack_56bit { substr(pack('Q>', $_[0]), 1) }
sub pack_64bit { pack('Q>', $_[0]) }
{
my %packers = (
8 => \&pack_8bit, 40 => \&pack_40bit,
16 => \&pack_16bit, 48 => \&pack_48bit,
24 => \&pack_24bit, 56 => \&pack_56bit,
32 => \&pack_32bit, 64 => \&pack_64bit,
);
sub pack_num {
my $packer = $packers{$_[0]}
or die;
return $packer->($_[1]);
}
sub get_packer {
my $packer = $packers{$_[0]}
or die;
return $packer;
}
}
my $packed = pack_num(40, 7);
-or-
my $packer = get_packer(40);
my $packed = $packer->(7);
如果您打算将多个数字打包成一个字符串(如 pack('L>*', @nums)
),我也会像这样使用调度 table,尽管我不确定会是什么pack_24bit
、pack_40bit
、pack_48bit
和 pack_56bit
的最快实现(C 解决方案除外)。
我想在 N 位容器中编码数字并在 UDP 数据包中发送它们。接收者将知道 N,并且接收者将从恰好 N 位中获取一个数字。(N <= 64)
有些想法是这样的:
sub to56BIT {
return pack("??", shift);
}
sub to24BIT {
return pack("??", shift);
}
my $n = 7;
to24BIT($n);
接收方:
int n = Get_val24(byte_stream, offset);
有没有办法在 Perl 中做到这一点?
我认为解决方案可能是:
sub packIntN {
my $int = shift;
my $length = shift;
return pack("B" . $length, substr(unpack("B64", pack("Q>", $int)), 64 - $length));
}
但也许还有更优雅的方式。
Input/Output 示例: 我们有一个脚本 test.pl:
use strict;
use warnings;
sub to24BIT {
#???
}
my $n = 7;
print to24BIT($n);
我想要这个:
./test.pl | hexdump -C
00000000 00 00 07 |...|
00000003
另一个脚本test2.pl:
use strict;
use warnings;
sub to40BIT {
#???
}
my $n = 7;
print to40BIT($n);
我想要这个:
./test.pl | hexdump -C
00000000 00 00 00 00 07 |.....|
00000005
请记住,您将永远拥有一个完整的 字节数,我最终得到
substr(pack("Q>",$n<<(64-$len)),0,($len+7)/8);
和
unpack("Q>",$s.(0 x 8)) >> (64-$len);
如本例所试:
#!/usr/bin/perl
$len = 40;
$n = 7;
$s = substr(pack("Q>",$n<<(64-$len)),0,($len+7)/8);
open(PIPE,"| hexdump -C");
print PIPE $s;
close PIPE;
$v = unpack("Q>",$s.(0 x 8)) >> (64-$len);
printf "%d\n",$v;
N 是否总是 8 的整数因子(8、16、24、32、40、48、56、64 之一)?如果是这样,为了速度,我建议为每种尺寸编写一个打包器,并使用调度 table 找到合适的打包器。
sub pack_8bit { pack('C', $_[0]) }
sub pack_16bit { pack('S>', $_[0]) }
sub pack_24bit { substr(pack('L>', $_[0]), 1) }
sub pack_32bit { pack('L>', $_[0]) }
sub pack_40bit { substr(pack('Q>', $_[0]), 3) }
sub pack_48bit { substr(pack('Q>', $_[0]), 2) }
sub pack_56bit { substr(pack('Q>', $_[0]), 1) }
sub pack_64bit { pack('Q>', $_[0]) }
{
my %packers = (
8 => \&pack_8bit, 40 => \&pack_40bit,
16 => \&pack_16bit, 48 => \&pack_48bit,
24 => \&pack_24bit, 56 => \&pack_56bit,
32 => \&pack_32bit, 64 => \&pack_64bit,
);
sub pack_num {
my $packer = $packers{$_[0]}
or die;
return $packer->($_[1]);
}
sub get_packer {
my $packer = $packers{$_[0]}
or die;
return $packer;
}
}
my $packed = pack_num(40, 7);
-or-
my $packer = get_packer(40);
my $packed = $packer->(7);
如果您打算将多个数字打包成一个字符串(如 pack('L>*', @nums)
),我也会像这样使用调度 table,尽管我不确定会是什么pack_24bit
、pack_40bit
、pack_48bit
和 pack_56bit
的最快实现(C 解决方案除外)。