- elsif ($template =~ /^Ca/) {
- $data->[0] = unpack 'C/a', $data->[0];
- }
- elsif ($template =~ /^(?:[xX]\d*)*$/) {
- next; # no values
+ else {
+ for (split m{(?![0-9*/])(?<![/=])}, $template) {
+ my ($type, $count) = m{^(\D+)(\d+)?$} or die 'unsupported';
+ my $mult = $count // 1;
+ given ($type) {
+ when (['c', 'C']) {
+ $$pos += $mult;
+ }
+ when ('x') {
+ $$pos += $mult;
+ next;
+ }
+ when (['b', 'B']) {
+ $$pos++;
+ }
+ when (['s', 'S', 'n', 'v']) {
+ $$pos += $mult * 2;
+ }
+ when (['a', 'A', 'Z', 'a*']) {
+ $$pos += length $data->[0];
+ }
+ when ('Z*') {
+ $$pos += $count // 1 + length $data->[0];
+ }
+ when (['C/a', 'C/A']) {
+ $$pos += 1 + ($count // length $data->[0]);
+ $data->[0] = unpack 'C/a', $data->[0] if defined $count;
+ }
+ when ('=') {
+ unshift @$data, $count;
+ }
+ when ('=.') {
+ unshift @$data, $$pos;
+ }
+ when ('X') {
+ $$pos -= $mult;
+ next;
+ }
+ default {
+ carp "Unrecognised template element '$type'";
+ }
+ }
+ if (defined $res{$field}) {
+ $res{$field} = [ $res{$field} ] unless ref $res{$field} eq 'ARRAY';
+ push @{ $res{$field} }, shift @$data;
+ }
+ else {
+ $res{$field} = shift @$data;
+ }
+ }