use strict; use warnings; use Benchmark qw( cmpthese ); use Inline C => <<'__EOI__'; /* unpack("FFFFL", sv) */ void custom_unpack(SV* sv) { dXSARGS; NV f1; NV f2; NV f3; NV f4; U32 u; STRLEN len; char* buf = SvPVbyte(sv, len); if (len != sizeof(NV)*4 + sizeof(U32)) croak("Length mismatch"); memcpy(&f1, buf, sizeof(NV)); buf += sizeof(NV); memcpy(&f2, buf, sizeof(NV)); buf += sizeof(NV); memcpy(&f3, buf, sizeof(NV)); buf += sizeof(NV); memcpy(&f4, buf, sizeof(NV)); buf += sizeof(NV); memcpy(&u, buf, sizeof(U32)); SP -= items; EXTEND(SP, 5); mPUSHn(f1); mPUSHn(f2); mPUSHn(f3); mPUSHn(f4); mPUSHu(u); XSRETURN(5); } /* unpack("FFFFL", sv) */ /* Only works on machine where NV */ /* and U32 can be byte-aligned */ void custom_unpack_nonportable(SV* sv) { dXSARGS; STRLEN len; char* buf = SvPVbyte(sv, len); if (len != sizeof(NV)*4 + sizeof(U32)) croak("Length mismatch"); SP -= items; EXTEND(SP, 5); mPUSHn(*(NV*)buf); mPUSHn(*(NV*)(buf + sizeof(NV))); mPUSHn(*(NV*)(buf + sizeof(NV)*2)); mPUSHn(*(NV*)(buf + sizeof(NV)*3)); mPUSHn(*(U32*)(buf + sizeof(NV)*4)); XSRETURN(5); } /* unpack("FFFFL", sv) */ /* Doesn't get magic */ /* Doesn't stringify */ /* Doesn't switch string format */ /* Doesn't do size checks */ /* Only works on machine where NV */ /* and U32 can be byte-aligned */ void custom_unpack_unsafe(SV* sv) { dXSARGS; char* buf = SvPVX(sv); SP -= items; EXTEND(SP, 5); mPUSHn(*(NV*)buf); mPUSHn(*(NV*)(buf + sizeof(NV))); mPUSHn(*(NV*)(buf + sizeof(NV)*2)); mPUSHn(*(NV*)(buf + sizeof(NV)*3)); mPUSHn(*(U32*)(buf + sizeof(NV)*4)); XSRETURN(5); } __EOI__ my %tests = ( 'unpack' => 'my @x = unpack("FFFFL", $buf);', 'custom' => 'my @x = custom_unpack($buf);', 'nonportable' => 'my @x = custom_unpack_nonportable($buf);', 'unsafe' => 'my @x = custom_unpack_unsafe($buf);', ); $_ = 'use strict; use warnings; our $buf; ' . $_ for values(%tests); local our $buf = pack('FFFFL', 1.2, 1.4, 1.8, 12345678.90123, 0x80000000); printf("unpack: %f %f %f %f %u\n", unpack("FFFFL", $buf)); printf("custom: %f %f %f %f %u\n", custom_unpack($buf)); printf("nonportable: %f %f %f %f %u\n", custom_unpack_nonportable($buf)); printf("unsafe: %f %f %f %f %u\n", custom_unpack_unsafe($buf)); cmpthese(-2, \%tests);