PHP Pack / unpack – может обрабатывать строки переменной длины

Я пытался выяснить, может ли реализация PHP Pack / Unpack сделать что-то, что может сделать версия 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, описывается как:

Объединение двух кодов пакетов с косой чертой (/) связывает их с одним значением из списка аргументов. В пакете длина аргумента берется и упаковывается в соответствии с первым кодом, в то время как сам аргумент добавляется после преобразования с кодом шаблона после косой черты.

т.е. вы можете упаковать строки переменной длины, а затем распаковать их за один шаг, вместо того, чтобы сначала определить длину строки, а затем извлечь ее как отдельный шаг.

В руководстве по PHP не упоминается эта возможность, и любая попытка вставить шаблон, подобный «C / A *», в распаковку дает мне ошибки. Это надзор в руководстве или просто то, что версия PHP не поддерживает?

Функции PHP pack и unpack, к сожалению, не обеспечивают автоматическую упаковку и распаковку строк с переменными (с нулевым завершением), например 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}'"); } } } 

Обратите внимание, что эта функция не реализует все типы распаковки и просто служит в качестве примера.