PHP Pack / unpack - can handle variable length strings

I was trying to figure out if the implementation of the PHP Pack / Unpack can do something that the version of Perl can do. An example I would like to do in 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 ); 

What this Perl code does is described as:

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

i.e. you can pack variable-length strings and then unpack them in one step, instead of first determining the length of the string and then extracting it as a separate step.

The PHP manual does not mention this feature, and any attempt to insert a template such as "C / A *" in unpack gives me errors. Is this oversight in the manual or just something that the PHP version does not support?

+3
source share
1 answer

The functions of the PHP package and unpacking, unfortunately, do not provide automatic packaging and unpacking of strings with variables (with zero completion) of the Perl type.

To perform this function, consider moving the unpack function to a helper class as follows:

 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 types of unpacking and just serves as an example.

+5
source

Source: https://habr.com/ru/post/921204/


All Articles