2010-09-01 11:22:43 +09:00
|
|
|
package Data::MessagePack::PP;
|
|
|
|
|
|
|
|
use 5.008000;
|
|
|
|
use strict;
|
|
|
|
use Carp ();
|
|
|
|
|
2010-09-01 11:59:01 +09:00
|
|
|
our $VERSION = '0.15';
|
2010-09-01 11:22:43 +09:00
|
|
|
|
|
|
|
# See also
|
|
|
|
# http://redmine.msgpack.org/projects/msgpack/wiki/FormatSpec
|
|
|
|
# http://cpansearch.perl.org/src/YAPPO/Data-Model-0.00006/lib/Data/Model/Driver/Memcached.pm
|
|
|
|
# http://frox25.no-ip.org/~mtve/wiki/MessagePack.html : reference to using CORE::pack, CORE::unpack
|
|
|
|
|
|
|
|
|
2010-09-01 11:59:01 +09:00
|
|
|
package
|
|
|
|
Data::MessagePack;
|
|
|
|
|
|
|
|
use Scalar::Util qw( blessed );
|
|
|
|
use strict;
|
|
|
|
use B ();
|
|
|
|
|
2010-09-01 11:22:43 +09:00
|
|
|
BEGIN {
|
|
|
|
# for pack and unpack compatibility
|
|
|
|
if ( $] < 5.010 ) {
|
|
|
|
require Data::Float;
|
|
|
|
*pack_double = sub {
|
|
|
|
my $float_hex = Data::Float::float_hex( $_[0] );
|
|
|
|
my ( $sign, $sgnf, $exp ) = $float_hex =~ /^([-+])0x1\.([a-z0-9]+)p([-+][\d]+)$/;
|
|
|
|
my @bits;
|
|
|
|
|
|
|
|
$sign = $sign eq '-' ? 1 : 0;
|
|
|
|
$exp = sprintf( '%011b', 1023 + $exp );
|
|
|
|
|
|
|
|
my $bit = $sign . $exp . join( '', map { unpack('B4', pack('H', $_) ) } split //, $sgnf );
|
|
|
|
|
|
|
|
while ( $bit =~ /(.{8})/g ) {
|
|
|
|
push @bits, $1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pack( 'C*', 0xcb, map { unpack( 'C', pack("B*", $_ ) ) } @bits );
|
|
|
|
};
|
|
|
|
*unpack_double = sub {
|
|
|
|
my $bits = join('', map { sprintf('%08b', $_) } unpack( 'C*', substr( $_[0], $_[1], 8 ) ) );
|
|
|
|
my $sign = substr($bits, 0, 1) ? '-' : '+';
|
|
|
|
my $sgnf = substr($bits, 12, 52);
|
|
|
|
my $exp = substr($bits, 1, 11);
|
|
|
|
$bits = '';
|
|
|
|
while ( $sgnf =~ /(.{4})/g ) {
|
|
|
|
$bits .= unpack('H',pack('B4', $1));
|
|
|
|
}
|
|
|
|
$exp = ((unpack("C*",(pack("B8", (substr('00000'.$exp,0,8) )))) <<8 )
|
|
|
|
+ unpack("C*",(pack("B8", (substr('00000'.$exp,8,8) ))))) - 1023;
|
|
|
|
return Data::Float::hex_float( $sign . '0x1.' . $bits . 'p' . $exp ) + 0.0;
|
|
|
|
};
|
|
|
|
*unpack_float = sub { Carp::croak("unpack_float is disable in less than Perl 5.10"); };
|
|
|
|
*unpack_int16 = sub {
|
|
|
|
my $v = unpack 'n', substr( $_[0], $_[1], 2 );
|
|
|
|
return $v ? $v - 0x10000 : 0;
|
|
|
|
};
|
|
|
|
*unpack_int32 = sub {
|
|
|
|
my $v = unpack 'N', substr( $_[0], $_[1], 4 );
|
|
|
|
return $v ? -(~$v + 1) : $v;
|
|
|
|
};
|
|
|
|
*unpack_int64 = sub { Carp::croak("unpack_int64 is disable in less than Perl 5.10"); };
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*pack_double = sub { return pack 'Cd>', 0xcb, $_[0]; };
|
|
|
|
*unpack_double = sub { return unpack( 'd>', substr( $_[0], $_[1], 8 ) ); };
|
|
|
|
*unpack_float = sub { return unpack( 'f>', substr( $_[0], $_[1], 4 ) ); };
|
|
|
|
*unpack_int16 = sub { return unpack 'n!', substr( $_[0], $_[1], 2 ); };
|
|
|
|
*unpack_int32 = sub { return unpack 'N!', substr( $_[0], $_[1], 4 ); };
|
|
|
|
*unpack_int64 = sub { return unpack 'Q>', substr( $_[0], $_[1], 8 ); };
|
|
|
|
}
|
|
|
|
# for 5.8 etc.
|
|
|
|
unless ( defined &utf8::is_utf8 ) {
|
|
|
|
require Encode;
|
|
|
|
*utf8::is_utf8 = *Encode::is_utf8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# PACK
|
|
|
|
#
|
|
|
|
|
|
|
|
{
|
2010-09-01 16:04:25 +09:00
|
|
|
no warnings 'recursion';
|
|
|
|
|
2010-09-01 11:22:43 +09:00
|
|
|
my $max_depth;
|
|
|
|
|
|
|
|
sub pack {
|
|
|
|
Carp::croak('Usage: Data::MessagePack->pack($dat [,$max_depth])') if @_ < 2;
|
|
|
|
$max_depth = defined $_[2] ? $_[2] : 512; # init
|
|
|
|
return _pack( $_[1] );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub _pack {
|
|
|
|
my ( $value ) = @_;
|
|
|
|
|
2010-09-01 16:04:25 +09:00
|
|
|
return CORE::pack( 'C', 0xc0 ) if ( not defined $value );
|
2010-09-01 11:22:43 +09:00
|
|
|
|
|
|
|
my $b_obj = B::svref_2object( ref $value ? $value : \$value );
|
|
|
|
|
|
|
|
if ( $b_obj->isa('B::AV') ) {
|
|
|
|
my $num = @$value;
|
|
|
|
my $header =
|
2010-09-01 16:04:25 +09:00
|
|
|
$num < 16 ? CORE::pack( 'C', 0x90 + $num )
|
|
|
|
: $num < 2 ** 16 - 1 ? CORE::pack( 'Cn', 0xdc, $num )
|
|
|
|
: $num < 2 ** 32 - 1 ? CORE::pack( 'CN', 0xdd, $num )
|
2010-09-01 11:22:43 +09:00
|
|
|
: die "" # don't arrivie here
|
|
|
|
;
|
|
|
|
if ( --$max_depth <= 0 ) {
|
|
|
|
Carp::croak("perl structure exceeds maximum nesting level (max_depth set too low?)");
|
|
|
|
}
|
|
|
|
return join( '', $header, map { _pack( $_ ) } @$value );
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( $b_obj->isa('B::HV') ) {
|
|
|
|
my $num = keys %$value;
|
|
|
|
my $header =
|
2010-09-01 16:04:25 +09:00
|
|
|
$num < 16 ? CORE::pack( 'C', 0x80 + $num )
|
|
|
|
: $num < 2 ** 16 - 1 ? CORE::pack( 'Cn', 0xde, $num )
|
|
|
|
: $num < 2 ** 32 - 1 ? CORE::pack( 'CN', 0xdf, $num )
|
2010-09-01 11:22:43 +09:00
|
|
|
: die "" # don't arrivie here
|
|
|
|
;
|
|
|
|
if ( --$max_depth <= 0 ) {
|
|
|
|
Carp::croak("perl structure exceeds maximum nesting level (max_depth set too low?)");
|
|
|
|
}
|
|
|
|
return join( '', $header, map { _pack( $_ ) } %$value );
|
|
|
|
}
|
|
|
|
|
2010-09-01 16:04:25 +09:00
|
|
|
elsif ( blessed( $value ) and blessed( $value ) eq 'Data::MessagePack::Boolean' ) {
|
|
|
|
return CORE::pack( 'C', $$value ? 0xc3 : 0xc2 );
|
2010-09-01 11:22:43 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
my $flags = $b_obj->FLAGS;
|
|
|
|
|
|
|
|
if ( $flags & ( B::SVf_IOK | B::SVp_IOK ) ) {
|
|
|
|
|
|
|
|
if ($value >= 0) {
|
2010-09-01 16:04:25 +09:00
|
|
|
return $value <= 127 ? CORE::pack 'C', $value
|
|
|
|
: $value < 2 ** 8 ? CORE::pack 'CC', 0xcc, $value
|
|
|
|
: $value < 2 ** 16 ? CORE::pack 'Cn', 0xcd, $value
|
|
|
|
: $value < 2 ** 32 ? CORE::pack 'CN', 0xce, $value
|
|
|
|
: CORE::pack 'CQ>', 0xcf, $value;
|
2010-09-01 11:22:43 +09:00
|
|
|
}
|
|
|
|
else {
|
2010-09-01 16:04:25 +09:00
|
|
|
return -$value <= 32 ? CORE::pack 'C', ($value & 255)
|
|
|
|
: -$value <= 2 ** 7 ? CORE::pack 'Cc', 0xd0, $value
|
|
|
|
: -$value <= 2 ** 15 ? CORE::pack 'Cn', 0xd1, $value
|
|
|
|
: -$value <= 2 ** 31 ? CORE::pack 'CN', 0xd2, $value
|
|
|
|
: CORE::pack 'Cq>', 0xd3, $value;
|
2010-09-01 11:22:43 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( $flags & B::SVf_POK ) { # raw / check needs before dboule
|
|
|
|
|
2010-09-01 11:59:01 +09:00
|
|
|
if ( $Data::MessagePack::PreferInteger ) {
|
2010-09-01 11:22:43 +09:00
|
|
|
if ( $value =~ /^-?[0-9]+$/ ) { # ok?
|
|
|
|
my $value2 = 0 + $value;
|
|
|
|
if ( 0 + $value != B::svref_2object( \$value2 )->int_value ) {
|
2010-09-01 11:59:01 +09:00
|
|
|
local $Data::MessagePack::PreferInteger; # avoid for PV => NV
|
2010-09-01 11:22:43 +09:00
|
|
|
return _pack( "$value" );
|
|
|
|
}
|
|
|
|
return _pack( $value + 0 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
utf8::encode( $value ) if utf8::is_utf8( $value );
|
|
|
|
|
|
|
|
my $num = length $value;
|
|
|
|
my $header =
|
2010-09-01 16:04:25 +09:00
|
|
|
$num < 32 ? CORE::pack( 'C', 0xa0 + $num )
|
|
|
|
: $num < 2 ** 16 - 1 ? CORE::pack( 'Cn', 0xda, $num )
|
|
|
|
: $num < 2 ** 32 - 1 ? CORE::pack( 'CN', 0xdb, $num )
|
2010-09-01 11:22:43 +09:00
|
|
|
: die "" # don't arrivie here
|
|
|
|
;
|
|
|
|
|
|
|
|
return $header . $value;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( $flags & ( B::SVf_NOK | B::SVp_NOK ) ) { # double only
|
|
|
|
return pack_double( $value );
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
die "???";
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} # PACK
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# UNPACK
|
|
|
|
#
|
|
|
|
|
|
|
|
{
|
2010-09-01 16:04:25 +09:00
|
|
|
|
2010-09-01 11:22:43 +09:00
|
|
|
my $p; # position variables for speed.
|
|
|
|
|
|
|
|
sub unpack {
|
|
|
|
$p = 0; # init
|
|
|
|
_unpack( $_[1] );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub _unpack {
|
|
|
|
my ( $value ) = @_;
|
2010-09-01 16:04:25 +09:00
|
|
|
my $byte = CORE::unpack( 'C', substr( $value, $p++, 1 ) ); # get header
|
2010-09-01 11:22:43 +09:00
|
|
|
|
|
|
|
die "invalid data" unless defined $byte;
|
|
|
|
|
|
|
|
if ( ( $byte >= 0x90 and $byte <= 0x9f ) or $byte == 0xdc or $byte == 0xdd ) {
|
|
|
|
my $num;
|
|
|
|
if ( $byte == 0xdc ) { # array 16
|
2010-09-01 16:04:25 +09:00
|
|
|
$num = CORE::unpack 'n', substr( $value, $p, 2 );
|
2010-09-01 11:22:43 +09:00
|
|
|
$p += 2;
|
|
|
|
}
|
|
|
|
elsif ( $byte == 0xdd ) { # array 32
|
2010-09-01 16:04:25 +09:00
|
|
|
$num = CORE::unpack 'N', substr( $value, $p, 4 );
|
2010-09-01 11:22:43 +09:00
|
|
|
$p += 4;
|
|
|
|
}
|
|
|
|
else { # fix array
|
|
|
|
$num = $byte & ~0x90;
|
|
|
|
}
|
|
|
|
my @array;
|
|
|
|
push @array, _unpack( $value ) while $num-- > 0;
|
|
|
|
return \@array;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( ( $byte >= 0x80 and $byte <= 0x8f ) or $byte == 0xde or $byte == 0xdf ) {
|
|
|
|
my $num;
|
|
|
|
if ( $byte == 0xde ) { # map 16
|
2010-09-01 16:04:25 +09:00
|
|
|
$num = CORE::unpack 'n', substr( $value, $p, 2 );
|
2010-09-01 11:22:43 +09:00
|
|
|
$p += 2;
|
|
|
|
}
|
|
|
|
elsif ( $byte == 0xdf ) { # map 32
|
2010-09-01 16:04:25 +09:00
|
|
|
$num = CORE::unpack 'N', substr( $value, $p, 4 );
|
2010-09-01 11:22:43 +09:00
|
|
|
$p += 4;
|
|
|
|
}
|
|
|
|
else { # fix map
|
|
|
|
$num = $byte & ~0x80;
|
|
|
|
}
|
|
|
|
my %map;
|
|
|
|
for ( 0 .. $num - 1 ) {
|
2010-09-01 16:04:25 +09:00
|
|
|
no warnings; # for undef key case
|
2010-09-01 11:22:43 +09:00
|
|
|
my $key = _unpack( $value );
|
|
|
|
my $val = _unpack( $value );
|
|
|
|
$map{ $key } = $val;
|
|
|
|
}
|
|
|
|
return \%map;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( $byte >= 0x00 and $byte <= 0x7f ) { # positive fixnum
|
|
|
|
return $byte;
|
|
|
|
}
|
|
|
|
elsif ( $byte == 0xcc ) { # uint8
|
2010-09-01 16:04:25 +09:00
|
|
|
CORE::unpack( 'C', substr( $value, $p++, 1 ) );
|
2010-09-01 11:22:43 +09:00
|
|
|
}
|
|
|
|
elsif ( $byte == 0xcd ) { # uint16
|
|
|
|
$p += 2;
|
2010-09-01 16:04:25 +09:00
|
|
|
return CORE::unpack 'n', substr( $value, $p - 2, 2 );
|
2010-09-01 11:22:43 +09:00
|
|
|
}
|
|
|
|
elsif ( $byte == 0xce ) { # unit32
|
|
|
|
$p += 4;
|
2010-09-01 16:04:25 +09:00
|
|
|
return CORE::unpack 'N', substr( $value, $p - 4, 4 );
|
2010-09-01 11:22:43 +09:00
|
|
|
}
|
|
|
|
elsif ( $byte == 0xcf ) { # unit64
|
|
|
|
$p += 8;
|
2010-09-01 16:04:25 +09:00
|
|
|
return CORE::unpack 'Q>', substr( $value, $p - 8, 8 );
|
2010-09-01 11:22:43 +09:00
|
|
|
}
|
|
|
|
elsif ( $byte == 0xd3 ) { # int64
|
|
|
|
$p += 8;
|
|
|
|
return unpack_int64( $value, $p - 8 );
|
|
|
|
}
|
|
|
|
elsif ( $byte == 0xd2 ) { # int32
|
|
|
|
$p += 4;
|
|
|
|
return unpack_int32( $value, $p - 4 );
|
|
|
|
}
|
|
|
|
elsif ( $byte == 0xd1 ) { # int16
|
|
|
|
$p += 2;
|
|
|
|
return unpack_int16( $value, $p - 2 );
|
|
|
|
}
|
|
|
|
elsif ( $byte == 0xd0 ) { # int8
|
2010-09-01 16:04:25 +09:00
|
|
|
return CORE::unpack 'c', substr( $value, $p++, 1 ); # c / C
|
2010-09-01 11:22:43 +09:00
|
|
|
}
|
|
|
|
elsif ( $byte >= 0xe0 and $byte <= 0xff ) { # negative fixnum
|
|
|
|
return $byte - 256;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( ( $byte >= 0xa0 and $byte <= 0xbf ) or $byte == 0xda or $byte == 0xdb ) { # raw
|
|
|
|
my $num;
|
|
|
|
if ( $byte == 0xda ) {
|
2010-09-01 16:04:25 +09:00
|
|
|
$num = CORE::unpack 'n', substr( $value, $p, 2 );
|
2010-09-01 11:22:43 +09:00
|
|
|
$p += 2 + $num;
|
|
|
|
}
|
|
|
|
elsif ( $byte == 0xdb ) {
|
2010-09-01 16:04:25 +09:00
|
|
|
$num = CORE::unpack 'N', substr( $value, $p, 4 );
|
2010-09-01 11:22:43 +09:00
|
|
|
$p += 4 + $num;
|
|
|
|
}
|
|
|
|
else { # fix raw
|
|
|
|
$num = $byte & ~0xa0;
|
|
|
|
$p += $num;
|
|
|
|
}
|
|
|
|
return substr( $value, $p - $num, $num );
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( $byte == 0xc0 ) { # nil
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
elsif ( $byte == 0xc2 ) { # boolean
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
elsif ( $byte == 0xc3 ) { # boolean
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( $byte == 0xcb ) { # double
|
|
|
|
$p += 8;
|
|
|
|
return unpack_double( $value, $p - 8 );
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( $byte == 0xca ) { # float
|
|
|
|
$p += 4;
|
|
|
|
return unpack_float( $value, $p - 4 );
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
die "???";
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} # UNPACK
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# Data::MessagePack::Unpacker
|
|
|
|
#
|
|
|
|
|
2010-09-01 11:59:01 +09:00
|
|
|
package
|
|
|
|
Data::MessagePack::Unpacker;
|
2010-09-01 11:22:43 +09:00
|
|
|
|
|
|
|
use strict;
|
|
|
|
|
|
|
|
sub new {
|
|
|
|
bless { stack => [] }, shift;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub execute_limit {
|
|
|
|
execute( @_ );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
my $p;
|
|
|
|
|
|
|
|
sub execute {
|
|
|
|
my ( $self, $data, $offset, $limit ) = @_;
|
|
|
|
my $value = substr( $data, $offset, $limit ? $limit : length $data );
|
|
|
|
my $len = length $value;
|
|
|
|
|
|
|
|
$p = 0;
|
|
|
|
|
|
|
|
while ( $len > $p ) {
|
|
|
|
_count( $self, $value ) or last;
|
|
|
|
|
|
|
|
if ( @{ $self->{stack} } > 0 ) {
|
|
|
|
pop @{ $self->{stack} } if --$self->{stack}->[-1] == 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( $len == $p ) {
|
|
|
|
$self->{ data } .= substr( $value, 0, $p );
|
|
|
|
$self->{ remain } = undef;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $p;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub _count {
|
|
|
|
my ( $self, $value ) = @_;
|
|
|
|
my $byte = unpack( 'C', substr( $value, $p++, 1 ) ); # get header
|
|
|
|
|
|
|
|
if ( ( $byte >= 0x90 and $byte <= 0x9f ) or $byte == 0xdc or $byte == 0xdd ) {
|
|
|
|
my $num;
|
|
|
|
if ( $byte == 0xdc ) { # array 16
|
|
|
|
$num = unpack 'n', substr( $value, $p, 2 );
|
|
|
|
$p += 2;
|
|
|
|
}
|
|
|
|
elsif ( $byte == 0xdd ) { # array 32
|
|
|
|
$num = unpack 'N', substr( $value, $p, 4 );
|
|
|
|
$p += 4;
|
|
|
|
}
|
|
|
|
else { # fix array
|
|
|
|
$num = $byte & ~0x90;
|
|
|
|
}
|
|
|
|
|
|
|
|
push @{ $self->{stack} }, $num + 1;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( ( $byte >= 0x80 and $byte <= 0x8f ) or $byte == 0xde or $byte == 0xdf ) {
|
|
|
|
my $num;
|
|
|
|
if ( $byte == 0xde ) { # map 16
|
|
|
|
$num = unpack 'n', substr( $value, $p, 2 );
|
|
|
|
$p += 2;
|
|
|
|
}
|
|
|
|
elsif ( $byte == 0xdf ) { # map 32
|
|
|
|
$num = unpack 'N', substr( $value, $p, 4 );
|
|
|
|
$p += 4;
|
|
|
|
}
|
|
|
|
else { # fix map
|
|
|
|
$num = $byte & ~0x80;
|
|
|
|
}
|
|
|
|
|
|
|
|
push @{ $self->{stack} }, $num * 2 + 1; # a pair
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( $byte == 0xc0 or $byte == 0xc2 or $byte == 0xc3 ) { # nil, false, true
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( $byte >= 0x00 and $byte <= 0x7f ) { # positive fixnum
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( $byte >= 0xcc and $byte <= 0xcf ) { # uint
|
|
|
|
$p += $byte == 0xcc ? 1
|
|
|
|
: $byte == 0xcd ? 2
|
|
|
|
: $byte == 0xce ? 4
|
|
|
|
: $byte == 0xcf ? 8
|
|
|
|
: die;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( $byte >= 0xd0 and $byte <= 0xd3 ) { # int
|
|
|
|
$p += $byte == 0xd0 ? 1
|
|
|
|
: $byte == 0xd1 ? 2
|
|
|
|
: $byte == 0xd2 ? 4
|
|
|
|
: $byte == 0xd3 ? 8
|
|
|
|
: die;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( $byte >= 0xe0 and $byte <= 0xff ) { # negative fixnum
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( $byte >= 0xca and $byte <= 0xcb ) { # float, double
|
|
|
|
$p += $byte == 0xca ? 4 : 8;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( ( $byte >= 0xa0 and $byte <= 0xbf ) or $byte == 0xda or $byte == 0xdb ) {
|
|
|
|
my $num;
|
|
|
|
if ( $byte == 0xda ) {
|
|
|
|
$num = unpack 'n', substr( $value, $p, 2 );
|
|
|
|
$p += 2;
|
|
|
|
}
|
|
|
|
elsif ( $byte == 0xdb ) {
|
|
|
|
$num = unpack 'N', substr( $value, $p, 4 );
|
|
|
|
$p += 4;
|
|
|
|
}
|
|
|
|
else { # fix raw
|
|
|
|
$num = $byte & ~0xa0;
|
|
|
|
}
|
|
|
|
$p += $num;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
die "???";
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
} # execute
|
|
|
|
|
|
|
|
|
|
|
|
sub data {
|
|
|
|
my $data = Data::MessagePack->unpack( $_[0]->{ data } );
|
|
|
|
$_[0]->reset;
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub is_finished {
|
|
|
|
my ( $self ) = @_;
|
|
|
|
( scalar( @{ $self->{stack} } ) or defined $self->{ remain } ) ? 0 : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub reset {
|
|
|
|
$_[0]->{ stack } = [];
|
|
|
|
$_[0]->{ data } = undef;
|
|
|
|
$_[0]->{ remain } = undef;
|
|
|
|
}
|
|
|
|
|
|
|
|
1;
|
|
|
|
__END__
|
|
|
|
|
|
|
|
=pod
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
2010-09-01 11:59:01 +09:00
|
|
|
Data::MessagePack::PP - Pure Perl version of Data::MessagePack
|
2010-09-01 11:22:43 +09:00
|
|
|
|
|
|
|
=head1 LIMITATION
|
|
|
|
|
|
|
|
Currently this module works completely in Perl 5.10 or later.
|
|
|
|
In Perl 5.8.x, it requires L<Data::Float> and cannot unpack int64 and float (pack int64 too).
|
|
|
|
|
|
|
|
|
|
|
|
=head1 SEE ALSO
|
|
|
|
|
2010-09-01 11:59:01 +09:00
|
|
|
L<http://msgpack.sourceforge.jp/>,
|
2010-09-01 11:22:43 +09:00
|
|
|
L<Data::MessagePack>,
|
2010-09-01 11:59:01 +09:00
|
|
|
L<Data::Float>,
|
2010-09-01 11:22:43 +09:00
|
|
|
L<http://frox25.no-ip.org/~mtve/wiki/MessagePack.html>,
|
|
|
|
|
|
|
|
=head1 AUTHOR
|
|
|
|
|
|
|
|
makamaka
|
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify
|
|
|
|
it under the same terms as Perl itself.
|
|
|
|
|
|
|
|
=cut
|