Пожалуйста, проверьте, соответствует ли следующий демонстрационный код вашим требованиям.
Этот код
определяет га sh декодер подпрограммы
читает шестнадцатеричное представление байтов, предоставленных OP из DATA block
, преобразует прочитанные данные в двоичное представление $ data , используя pack
извлекает длина , ключ / тид , тип с использованием распаковка
вызов декодер подпрограмма для этого конкретного типа
возвращается ha sh, состоящий из двух массивов ключей и vals
образует новый ха sh % данных с предоставленными ключами и vals
выводит ключи и значения (возвращенные ключи используются для сохранения порядок байтов / полей)
ПРИМЕЧАНИЕ: Кодирование 'from_to' используется для декодирования EBCDI C - альтернатива
use strict;
use warnings;
use feature 'say';
use utf8;
use Encode 'from_to';
my $debug = 1;
my %decoder = (
1 => \&decode_type1,
2 => \&decode_currency,
3 => \&decode_type3,
4 => \&decode_type4,
5 => \&decode_type5
);
my $bytes = read_bytes();
my($len,$key,$type) = unpack('C3',$bytes);
my $data = $decoder{$type}($bytes);
my %data;
@data{@{$data->{keys}}} = @{$data->{vals}};
say '
Unpacked data
---------------';
printf "%-8s => %s\n", $_, $data{$_} for @{$data->{keys}};
sub read_bytes {
my $hex_bytes = <DATA>;
chomp $hex_bytes;
my $bytes = pack('H*',$hex_bytes);
return $bytes;
}
sub show_bytes {
my $data = shift;
print "Bytes: ";
printf "%02X ", $_ for unpack 'C*', $data;
print "\n";
}
sub decode_type1 {
my $bytes = shift;
return { keys => 'type1', vals => 'vals1' };
}
sub decode_currency {
my $bytes = shift;
show_bytes($bytes) if $debug;
my @keys = qw/length_1 key uid char data_1 length_2 val reserved data_2/;
my @vals = unpack('C4A8C2SA3',$bytes);
from_to($vals[4], 'cp37', 'latin1');
from_to($vals[8], 'cp37', 'latin1');
return { keys => \@keys, vals => \@vals};
}
sub decode_type3 {
my $bytes = shift;
return { keys => 'type3', vals => 'vals3' };
}
sub decode_type4 {
my $bytes = shift;
return { keys => 'type4', vals => 'vals4' };
}
sub decode_type5 {
my $bytes = shift;
return { keys => 'type5', vals => 'vals5' };
}
__DATA__
0C020B00C3A49999859583A807360000C5E4D9
Выход
Bytes: 0C 02 0B 00 C3 A4 99 99 85 95 83 A8 07 36 00 00 C5 E4 D9
Unpacked data
---------------
length_1 => 12
key => 2
uid => 11
char => 0
data_1 => Currency
length_2 => 7
val => 54
reserved => 0
data_2 => EUR
Примечание:
Выглядит подозрительно, что val занимает только один байт, что дает диапазон 0..255 для суммы в евро. Возможно, зарезервированные байты могут быть частью val суммы в евро.