PHP Pack/unpack - can it handle variable length strings

元气小坏坏 提交于 2019-12-04 04:34:01

问题


I've been trying to figure out if the PHP implementation of Pack/Unpack can do something that the Perl version is able to do. The example I'd like to be able to do in PHP is:

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 );

What this Perl code does is described as:

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.

i.e. you can pack variable length strings and then unpack them in one step, rather than having to figure out the length of the string first and then extracting it as a separate step.

The PHP manual doesn't mention this capability and any attempt to insert a pattern like 'C/A*' into unpack is giving errors for me. Is that an oversight in the manual or just something that the PHP version doesn't support?


回答1:


PHP pack and unpack functions unfortunately do not provide automatic packing and unpacking of variable (null terminated) strings like Perl.

To accommodate for this functionality, consider wrapping the unpack function into a helper class like this:

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}'");
        }
    }
}

Please note that this function does not implement all unpack types and merely serves as an example.



来源:https://stackoverflow.com/questions/11632773/php-pack-unpack-can-it-handle-variable-length-strings

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!