PHP Pack / unpack – 它可以处理可变长度的字符串

我一直试图弄清楚Pack / Unpack的PHP实现是否可以做Perl版本能够做的事情.我希望能用PHP做的例子是:

http://perldoc.perl.org/perlpacktut.html#String-Lengths

# pack a message: ASCIIZ, ASCIIZ, length/string, byte
my $msg = pack( 'Z* Z* C/A* C', $src, $dst, $sm, $prio );
# unpack
( $src, $dst, $sm, $prio ) = unpack( 'Z* Z* C/A* C', $msg );

这个Perl代码的作用描述如下:

Combining two pack codes with a slash (/) associates them with a
single value from the argument list. In pack, the length of the
argument is taken and packed according to the first code while the
argument itself is added after being converted with the template code
after the slash.

即你可以打包可变长度的字符串然后一步解压缩它们,而不是先弄清字符串的长度然后再将它作为一个单独的步骤解压缩.

PHP手册没有提到这个功能,任何尝试在解包中插入像’C / A *’这样的模式都给我带来了错误.这是手册中的疏忽还是PHP版本不支持的东西?

解决方法:

遗憾的是,PHP包和解包函数不提供像Perl这样的变量(空终止)字符串的自动打包和解包.

要适应此功能,请考虑将解包函数包装到这样的辅助类中:

class Packer {
    static function unpack($mask, $data, &$pos) {
        try {
            $result = array();
            $pos = 0;
            foreach($mask as $field) {
                $subject = substr($data, $pos);
                $type = $field[0];
                $name = $field[1];
                switch($type) {
                    case 'N':
                    case 'n':
                    case 'C':
                    case 'c':
                        $temp = unpack("{$type}temp", $subject);
                        $result[$name] = $temp['temp'];
                        if($type=='N') {
                            $result[$name] = (int)$result[$name];
                        }

                        $pos += ($type=='N' ? 4 : ($type=='n' ? 2 : 1));
                        break;
                    case 'a':
                        $nullPos = strpos($subject, "\0") + 1;
                        $temp = unpack("a{$nullPos}temp", $subject);
                        $result[$name] = $temp['temp'];
                        $pos += $nullPos;
                        break;
                }
            }
            return $result;
        } catch(Exception $e) {
            $message = $e->getMessage();
            throw new Exception("unpack Failed with error '{$message}'");
        }
    }
}

请注意,此函数不实现所有解压缩类型,仅作为示例.

相关文章

统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
前言 之前做了微信登录,所以总结一下微信授权登录并获取用户...
FastAdmin是我第一个接触的后台管理系统框架。FastAdmin是一...
之前公司需要一个内部的通讯软件,就叫我做一个。通讯软件嘛...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...