our
@ISA
=
qw{Data::ParseBinary::Adapter}
;
sub
_init {
my
(
$self
,
@params
) =
@_
;
my
$decode
= {};
my
$encode
= {};
$self
->{have_default} = 0;
$self
->{default_action} =
undef
;
while
(
@params
) {
my
$key
=
shift
@params
;
my
$value
=
shift
@params
;
if
(
$key
eq
'_default_'
) {
$self
->{have_default} = 1;
$self
->{default_action} =
$value
;
if
(
ref
$value
) {
if
(
$value
!=
$Data::ParseBinary::BaseConstruct::DefaultPass
) {
die
"Enum Error: got invalid value as default"
;
}
}
elsif
(
exists
$encode
->{
$value
}) {
die
"Enum Error: $value should not be defined as regular case"
;
}
else
{
$self
->{default_value} =
shift
@params
;
}
next
;
}
$encode
->{
$key
} =
$value
;
$decode
->{
$value
} =
$key
;
}
$self
->{encode} =
$encode
;
$self
->{decode} =
$decode
;
}
sub
_decode {
my
(
$self
,
$value
) =
@_
;
if
(
exists
$self
->{decode}->{
$value
}) {
return
$self
->{decode}->{
$value
};
}
if
(
$self
->{have_default}) {
if
(
ref
(
$self
->{default_action}) and
$self
->{default_action} ==
$Data::ParseBinary::BaseConstruct::DefaultPass
) {
return
$value
;
}
return
$self
->{default_action};
}
die
"Enum: unrecognized value $value, and no default defined"
;
}
sub
_encode {
my
(
$self
,
$tvalue
) =
@_
;
if
(
exists
$self
->{encode}->{
$tvalue
}) {
return
$self
->{encode}->{
$tvalue
};
}
if
(
$self
->{have_default}) {
if
(
ref
(
$self
->{default_action}) and
$self
->{default_action} ==
$Data::ParseBinary::BaseConstruct::DefaultPass
) {
return
$tvalue
;
}
return
$self
->{default_value};
}
die
"Enum: unrecognized value $tvalue"
;
}
our
@ISA
=
qw{Data::ParseBinary::Adapter}
;
sub
_init {
my
(
$self
,
@mapping
) =
@_
;
my
@pairs
;
die
"FlagsEnum: Mapping should be even"
if
@mapping
% 2 == 1;
while
(
@mapping
) {
my
$name
=
shift
@mapping
;
my
$value
=
shift
@mapping
;
push
@pairs
, [
$name
,
$value
];
}
$self
->{pairs} = \
@pairs
;
}
sub
_decode {
my
(
$self
,
$value
) =
@_
;
my
$hash
= {};
foreach
my
$rec
(@{
$self
->{pairs} }) {
$hash
->{
$rec
->[0]} = 1
if
$value
&
$rec
->[1];
}
return
$hash
;
}
sub
_encode {
my
(
$self
,
$tvalue
) =
@_
;
my
$value
= 0;
foreach
my
$rec
(@{
$self
->{pairs} }) {
if
(
exists
$tvalue
->{
$rec
->[0]} and
$tvalue
->{
$rec
->[0]}) {
$value
|=
$rec
->[1];
}
}
return
$value
;
}
our
@ISA
=
qw{Data::ParseBinary::Adapter}
;
sub
_init {
my
(
$self
,
$sub_name
) =
@_
;
$self
->{sub_name} =
$sub_name
;
}
sub
_decode {
my
(
$self
,
$value
) =
@_
;
return
$value
->{
$self
->{sub_name}};
}
sub
_encode {
my
(
$self
,
$tvalue
) =
@_
;
return
{
$self
->{sub_name} =>
$tvalue
};
}
our
@ISA
=
qw{Data::ParseBinary::Adapter}
;
sub
_init {
my
(
$self
,
$index
) =
@_
;
$self
->{
index
} =
$index
|| 0;
}
sub
_decode {
my
(
$self
,
$value
) =
@_
;
return
$value
->[
$self
->{
index
}];
}
sub
_encode {
my
(
$self
,
$tvalue
) =
@_
;
return
[ (
''
) x
$self
->{
index
},
$tvalue
];
}
our
@ISA
=
qw{Data::ParseBinary::Adapter}
;
sub
_decode {
my
(
$self
,
$value
) =
@_
;
return
join
''
,
@$value
;
}
sub
_encode {
my
(
$self
,
$tvalue
) =
@_
;
return
[
split
''
,
$tvalue
];
}
our
@ISA
=
qw{Data::ParseBinary::Adapter}
;
sub
_init {
my
(
$self
,
$value
) =
@_
;
$self
->{value} =
$value
;
}
sub
_decode {
my
(
$self
,
$value
) =
@_
;
if
(not
$value
eq
$self
->{value}) {
die
"Const Error: expected $self->{value} got $value"
;
}
return
$value
;
}
sub
_encode {
my
(
$self
,
$tvalue
) =
@_
;
if
(not
defined
$self
->_get_name()) {
return
$self
->{value};
}
if
(
defined
$tvalue
and
$tvalue
eq
$self
->{value}) {
return
$self
->{value};
}
die
"Const Error: expected $self->{value} got "
. (
defined
$tvalue
?
$tvalue
:
"undef"
);
}
our
@ISA
=
qw{Data::ParseBinary::Adapter}
;
sub
_decode {
my
(
$self
,
$value
) =
@_
;
return
$value
->[1];
}
sub
_encode {
my
(
$self
,
$tvalue
) =
@_
;
return
[
length
(
$tvalue
),
$tvalue
];
}
our
@ISA
=
qw{Data::ParseBinary::Adapter}
;
sub
_init {
my
(
$self
,
%params
) =
@_
;
if
(not
defined
$params
{
length
}) {
die
"PaddedStringAdapter: you must specify length"
;
}
$self
->{
length
} =
$params
{
length
};
$self
->{encoding} =
$params
{encoding};
$self
->{padchar} =
defined
$params
{padchar} ?
$params
{padchar} :
"\x00"
;
$self
->{paddir} =
$params
{paddir} ||
"right"
;
$self
->{trimdir} =
$params
{trimdir} ||
"right"
;
if
(not
grep
(
$_
eq
$self
->{paddir},
qw{right left center}
)) {
die
"PaddedStringAdapter: paddir should be one of {right left center}"
;
}
if
(not
grep
(
$_
eq
$self
->{trimdir},
qw{right left}
)) {
die
"PaddedStringAdapter: trimdir should be one of {right left}"
;
}
}
sub
_decode {
my
(
$self
,
$value
) =
@_
;
my
$tvalue
=
$value
;
my
$char
=
$self
->{padchar};
if
(
$self
->{paddir} eq
'right'
or
$self
->{paddir} eq
'center'
) {
$tvalue
=~ s/
$char
*\z//;
}
elsif
(
$self
->{paddir} eq
'left'
or
$self
->{paddir} eq
'center'
) {
$tvalue
=~ s/\A
$char
*//;
}
return
$tvalue
;
}
sub
_encode {
my
(
$self
,
$tvalue
) =
@_
;
my
$value
=
$tvalue
;
if
(
length
(
$value
) <
$self
->{
length
}) {
my
$add
=
$self
->{
length
} -
length
(
$value
);
my
$char
=
$self
->{padchar};
if
(
$self
->{paddir} eq
'right'
) {
$value
.=
$char
x
$add
;
}
elsif
(
$self
->{paddir} eq
'left'
) {
$value
= (
$char
x
$add
) .
$value
;
}
elsif
(
$self
->{paddir} eq
'center'
) {
my
$add_left
=
$add
/ 2;
my
$add_right
=
$add_left
+ (
$add
% 2 == 0 ? 0 : 1);
$value
= (
$char
x
$add_left
) .
$value
. (
$char
x
$add_right
);
}
}
if
(
length
(
$value
) >
$self
->{
length
}) {
my
$remove
=
length
(
$value
) -
$self
->{
length
};
if
(
$self
->{trimdir} eq
'right'
) {
substr
(
$value
,
$self
->{
length
},
$remove
,
''
);
}
elsif
(
$self
->{trimdir} eq
'left'
) {
substr
(
$value
, 0,
$remove
,
''
);
}
}
return
$value
;
}
our
@ISA
=
qw{Data::ParseBinary::Adapter}
;
sub
_init {
my
(
$self
,
$terminators
) =
@_
;
$self
->{regex} =
qr/[$terminators]*\z/
;
$self
->{terminator} =
substr
(
$terminators
, 0, 1);
}
sub
_decode {
my
(
$self
,
$value
) =
@_
;
$value
=~ s/
$self
->{regex}//;
return
$value
;
}
sub
_encode {
my
(
$self
,
$tvalue
) =
@_
;
return
$tvalue
.
$self
->{terminator};
}
our
@ISA
=
qw{Data::ParseBinary::Validator}
;
sub
_init {
my
(
$self
,
@params
) =
@_
;
$self
->{coderef} =
shift
@params
;
}
sub
_validate {
my
(
$self
,
$value
) =
@_
;
return
$self
->{coderef}->(
$value
);
}
our
@ISA
=
qw{Data::ParseBinary::Adapter}
;
sub
_init {
my
(
$self
,
$unit_length
,
$first_name
,
$the_rest
) =
@_
;
$first_name
||=
'FirstUnit'
;
$the_rest
||=
'TheRest'
;
$self
->{unit_length} =
$unit_length
;
$self
->{first_name} =
$first_name
;
$self
->{the_rest} =
$the_rest
;
}
sub
_decode {
my
(
$self
,
$value
) =
@_
;
$value
=
join
(
''
,
$value
->{
$self
->{first_name}}, @{
$value
->{
$self
->{the_rest}} } );
return
$value
;
}
sub
_encode {
my
(
$self
,
$tvalue
) =
@_
;
my
$u_len
=
$self
->{unit_length};
die
"Length of input should be dividable by unit_length"
unless
length
(
$tvalue
) %
$u_len
== 0;
my
@units
=
map
substr
(
$tvalue
,
$_
*$u_len
,
$u_len
), 0..(
length
(
$tvalue
) /
$u_len
- 1);
my
$first
=
shift
@units
;
my
$value
= {
$self
->{first_name} =>
$first
,
$self
->{the_rest} => \
@units
};
return
$value
;
}
our
@ISA
=
qw{Data::ParseBinary::Adapter}
;
sub
_init {
my
(
$self
,
$encoding
) =
@_
;
$self
->{encoding} =
$encoding
;
}
sub
_decode {
my
(
$self
,
$octets
) =
@_
;
my
$string
= Encode::decode(
$self
->{encoding},
$octets
);
return
$string
;
}
sub
_encode {
my
(
$self
,
$string
) =
@_
;
my
$octets
= Encode::encode(
$self
->{encoding},
$string
);
return
$octets
;
}
our
@ISA
=
qw{Data::ParseBinary::Adapter}
;
sub
_init {
my
(
$self
,
$is_signed
,
$is_bigendian
) =
@_
;
$self
->{is_signed} =
$is_signed
;
$self
->{is_bigendian} =
$is_bigendian
;
}
sub
_decode {
my
(
$self
,
$value
) =
@_
;
if
(not
$self
->{is_bigendian}) {
$value
=
join
''
,
reverse
split
''
,
$value
;
}
my
$is_negative
;
if
(
$self
->{is_signed}) {
my
$first_char
=
ord
(
$value
);
if
(
$first_char
> 127) {
$value
= ~
$value
;
$is_negative
= 1;
}
}
my
$hexed
=
unpack
"H*"
,
$value
;
my
$number
= Math::BigInt->new(
"0x$hexed"
);
if
(
$is_negative
) {
$number
->binc()->bneg();
}
return
$number
;
}
sub
_encode {
my
(
$self
,
$number
) =
@_
;
$number
= Math::BigInt->new(
$number
);
my
$is_negative
;
if
(
$self
->{is_signed}) {
if
(
$number
->sign() eq
'-'
) {
$is_negative
= 1;
$number
->binc()->babs();
}
}
else
{
if
(
$number
->sign() eq
'-'
) {
die
"Was given a negative number for unsigned integer"
;
}
}
my
$hexed
=
$number
->as_hex();
substr
(
$hexed
, 0, 2,
''
);
my
$packed
=
pack
"H*"
, (
"0"
x(16-
length
(
$hexed
))).
$hexed
;
if
(
$is_negative
) {
$packed
= ~
$packed
;
}
if
(not
$self
->{is_bigendian}) {
$packed
=
join
''
,
reverse
split
''
,
$packed
;
}
return
$packed
;
}
1;