3 # Check conversions of PV to NV/IV/UV
9 skip_all_without_dynamic_extension('Devel::Peek');
17 # Use Devel::Peek::Dump in order to investigate SV flags for checking
18 # conversion behavior precisely.
19 # But unfortunately Devel::Peek::Dump always outputs to stderr, so
20 # a small wrapper to capture stderr into Perl string is implemented here
21 # to automate the test.
25 open my $old, '>&', *STDERR or die "Can't save STDERR: $!";
27 open STDERR, $_[1], $_[2] or die "Can't redirect STDERR: $!";
28 bless \$old, $_[0] || __PACKAGE__;
31 open STDERR, '>&', ${$_[0]} or die "Can't restore STDERR: $!";
36 # These functions use &sub form to minimize argument manipulation.
43 local $SIG{__WARN__} = sub { push @warnings, $_[0] };
44 my $err = STDERRSaver->new('>', \$str);
47 } or BAIL_OUT $@; # Avoid die() under test.
48 note(@warnings) if @warnings;
52 # Implement Sv*OK in Perl.
56 my $dump = &capture_dump;
57 $dump =~ /^\h*FLAGS\h*=\h*\(\h*(.*?)\h*\)/m # be tolerant
58 or note($dump), BAIL_OUT 'Cannot parse Devel::Peek::Dump output';
59 +{ map { $_ => !0 } split /\h*,\h*/, $1 };
64 my $flags = &sv_flags;
65 $flags->{IOK} && $flags->{IsUV};
70 my $flags = &sv_flags;
71 $flags->{pIOK} && $flags->{IsUV};
74 sub SvIOKp_notIOK_notUV
76 my $flags = &sv_flags;
77 $flags->{pIOK} && !$flags->{IOK} && !$flags->{IsUV};
82 my $flags = &sv_flags;
83 $flags->{IOK} && !$flags->{IsUV};
91 # This will be a quick test of Sv*OK* implemented here.
92 ok(SvIOK_notUV(2147483647), '2147483647 is not UV');
97 my $z = $y << 0; # "<<" requires UV operands
98 is($z, 12345, "string '$x' to UV conversion");
99 ok(SvIOKp_notIOK_notUV($y), 'string to UV conversion caches IV');
100 is($y >> 0, 12345, 'reusing cached IV');
106 my $z = $y | 0; # "|" also requires UV operands
107 is($z, 4000000000, "string '$x' to UV conversion");
108 ok(SvNOK($y), "string to UV conversion caches NV");
109 ok(SvUOK(4000000000) ? SvUOK($y) : SvIOK_notUV($y),
110 'string to UV conversion caches IV or UV');
111 is($y ^ 0, 4000000000, 'reusing cached IV or UV');
117 my $x = $uv_max * 7; # Some large value not representable in IV/UV
118 my $y = "$x"; # Convert to string
120 is($z, $uv_max, 'large value in string is coerced to UV_MAX when UV is requested');
121 ok(SvUOKp($y), 'converted UV is cached');
122 is($y >> 0, $uv_max, 'reusing cached UV_MAX');
123 my $v = $x << 0; # Now NV to UV conversion
124 is($v, $uv_max, 'large NV is coerced to UV_MAX when UV is requested');
125 ok(SvUOKp($v), 'converted UV is cached');
126 is($x >> 0, $uv_max, 'reusing cached UV_MAX');