Skip to content

Commit b9631cb

Browse files
committed
add sv_numle(), sv_numlt(), sv_numge(), sv_numgt() APIs
These are all needed because overloading may make them inconsistent with <=> overloading.
1 parent baccd98 commit b9631cb

File tree

8 files changed

+230
-4
lines changed

8 files changed

+230
-4
lines changed

MANIFEST

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5193,6 +5193,7 @@ ext/XS-APItest/t/subcall.t Test XSUB calls
51935193
ext/XS-APItest/t/subsignature.t Test parse_subsignature()
51945194
ext/XS-APItest/t/sv_numcmp.t Test sv_numcmp
51955195
ext/XS-APItest/t/sv_numeq.t Test sv_numeq
5196+
ext/XS-APItest/t/sv_numlget.t Test sv_num[lg][et]
51965197
ext/XS-APItest/t/sv_numne.t Test sv_numne
51975198
ext/XS-APItest/t/sv_streq.t Test sv_streq
51985199
ext/XS-APItest/t/svcat.t Test sv_catpvn

embed.fnc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3424,6 +3424,26 @@ Admp |bool |sv_numeq |NULLOK SV *sv1 \
34243424
Adp |bool |sv_numeq_flags |NULLOK SV *sv1 \
34253425
|NULLOK SV *sv2 \
34263426
|const U32 flags
3427+
Admp |bool |sv_numge |NULLOK SV *sv1 \
3428+
|NULLOK SV *sv2
3429+
Adp |bool |sv_numge_flags |NULLOK SV *sv1 \
3430+
|NULLOK SV *sv2 \
3431+
|const U32 flags
3432+
Admp |bool |sv_numgt |NULLOK SV *sv1 \
3433+
|NULLOK SV *sv2
3434+
Adp |bool |sv_numgt_flags |NULLOK SV *sv1 \
3435+
|NULLOK SV *sv2 \
3436+
|const U32 flags
3437+
Admp |bool |sv_numle |NULLOK SV *sv1 \
3438+
|NULLOK SV *sv2
3439+
Adp |bool |sv_numle_flags |NULLOK SV *sv1 \
3440+
|NULLOK SV *sv2 \
3441+
|const U32 flags
3442+
Admp |bool |sv_numlt |NULLOK SV *sv1 \
3443+
|NULLOK SV *sv2
3444+
Adp |bool |sv_numlt_flags |NULLOK SV *sv1 \
3445+
|NULLOK SV *sv2 \
3446+
|const U32 flags
34273447
Admp |bool |sv_numne |NULLOK SV *sv1 \
34283448
|NULLOK SV *sv2
34293449
Adp |bool |sv_numne_flags |NULLOK SV *sv1 \

embed.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,10 @@
728728
# define sv_nosharing(a) Perl_sv_nosharing(aTHX_ a)
729729
# define sv_numcmp_flags(a,b,c) Perl_sv_numcmp_flags(aTHX_ a,b,c)
730730
# define sv_numeq_flags(a,b,c) Perl_sv_numeq_flags(aTHX_ a,b,c)
731+
# define sv_numge_flags(a,b,c) Perl_sv_numge_flags(aTHX_ a,b,c)
732+
# define sv_numgt_flags(a,b,c) Perl_sv_numgt_flags(aTHX_ a,b,c)
733+
# define sv_numle_flags(a,b,c) Perl_sv_numle_flags(aTHX_ a,b,c)
734+
# define sv_numlt_flags(a,b,c) Perl_sv_numlt_flags(aTHX_ a,b,c)
731735
# define sv_numne_flags(a,b,c) Perl_sv_numne_flags(aTHX_ a,b,c)
732736
# define sv_peek(a) Perl_sv_peek(aTHX_ a)
733737
# define sv_pos_b2u(a,b) Perl_sv_pos_b2u(aTHX_ a,b)
@@ -2349,6 +2353,10 @@
23492353
# define Perl_sv_mortalcopy(mTHX,a) sv_mortalcopy(a)
23502354
# define Perl_sv_numcmp(mTHX,a,b) sv_numcmp(a,b)
23512355
# define Perl_sv_numeq(mTHX,a,b) sv_numeq(a,b)
2356+
# define Perl_sv_numge(mTHX,a,b) sv_numge(a,b)
2357+
# define Perl_sv_numgt(mTHX,a,b) sv_numgt(a,b)
2358+
# define Perl_sv_numle(mTHX,a,b) sv_numle(a,b)
2359+
# define Perl_sv_numlt(mTHX,a,b) sv_numlt(a,b)
23522360
# define Perl_sv_numne(mTHX,a,b) sv_numne(a,b)
23532361
# define Perl_sv_pv(mTHX,a) sv_pv(a)
23542362
# define Perl_sv_pvbyte(mTHX,a) sv_pvbyte(a)
@@ -2452,6 +2460,10 @@
24522460
# define Perl_sv_mortalcopy sv_mortalcopy
24532461
# define Perl_sv_numcmp sv_numcmp
24542462
# define Perl_sv_numeq sv_numeq
2463+
# define Perl_sv_numge sv_numge
2464+
# define Perl_sv_numgt sv_numgt
2465+
# define Perl_sv_numle sv_numle
2466+
# define Perl_sv_numlt sv_numlt
24552467
# define Perl_sv_numne sv_numne
24562468
# define Perl_sv_pv sv_pv
24572469
# define Perl_sv_pvbyte sv_pvbyte

ext/XS-APItest/APItest.xs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5044,6 +5044,30 @@ sv_numcmp(nullable_SV sv1, nullable_SV sv2)
50445044
I32
50455045
sv_numcmp_flags(nullable_SV sv1, nullable_SV sv2, U32 flags)
50465046

5047+
bool
5048+
sv_numle(nullable_SV sv1, nullable_SV sv2)
5049+
5050+
bool
5051+
sv_numle_flags(nullable_SV sv1, nullable_SV sv2, U32 flags)
5052+
5053+
bool
5054+
sv_numlt(nullable_SV sv1, nullable_SV sv2)
5055+
5056+
bool
5057+
sv_numlt_flags(nullable_SV sv1, nullable_SV sv2, U32 flags)
5058+
5059+
bool
5060+
sv_numge(nullable_SV sv1, nullable_SV sv2)
5061+
5062+
bool
5063+
sv_numge_flags(nullable_SV sv1, nullable_SV sv2, U32 flags)
5064+
5065+
bool
5066+
sv_numgt(nullable_SV sv1, nullable_SV sv2)
5067+
5068+
bool
5069+
sv_numgt_flags(nullable_SV sv1, nullable_SV sv2, U32 flags)
5070+
50475071
bool
50485072
sv_streq(SV *sv1, SV *sv2)
50495073
CODE:

ext/XS-APItest/t/sv_numlget.t

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!perl
2+
# tests the numeric sv_num[lg][te]() APIs
3+
4+
use Test::More;
5+
use XS::APItest;
6+
use strict;
7+
8+
# overloading
9+
package AlwaysTen {
10+
use overload
11+
'<=>' => sub {
12+
return $_[2] ? $_[1] <=> 10 : 10 <=> $_[1]
13+
},
14+
'0+' => sub { 123456 };
15+
}
16+
17+
# +0 overloading with large numbers and using fallback
18+
package MyBigNum {
19+
use overload
20+
"0+" => sub { $_[0][0] },
21+
fallback => 1;
22+
}
23+
24+
my @values =
25+
(
26+
[ ~0 ],
27+
[ ~0-1 ],
28+
[ -int(~0/2) ],
29+
[ 1.001 ],
30+
[ 1.002 ],
31+
[ bless([ ~0 ], "MyBigNum"), "bignum ~0" ],
32+
[ bless([ ~0 ], "MyBigNum"), "bignum ~0 #2" ],
33+
[ bless([ ~0-1 ], "MyBigNum"), "bignum ~0-1" ],
34+
[ undef(), "undef" ],
35+
[ 0+"NaN", "NaN" ],
36+
);
37+
38+
for my $x (@values) {
39+
for my $y (@values) {
40+
for my $func ( [ "le", sub { $_[0] <= $_[1] }, \&sv_numle ],
41+
[ "lt", sub { $_[0] < $_[1] }, \&sv_numlt ],
42+
[ "ge", sub { $_[0] >= $_[1] }, \&sv_numge ],
43+
[ "gt", sub { $_[0] > $_[1] }, \&sv_numgt ]) {
44+
my ($op, $native, $api) = @$func;
45+
my $lname = $x->[1] // $x->[0];
46+
my $rname = $y->[1] // $y->[0];
47+
is($api->($x->[0], $x->[1]), $native->($x->[0], $x->[1]),
48+
"$lname $op $rname");
49+
}
50+
}
51+
}
52+
53+
done_testing;

proto.h

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sv.c

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8742,6 +8742,14 @@ S_sv_numcmp_common(pTHX_ SV **sv1, SV **sv2, const U32 flags,
87428742
=for apidoc_item sv_numeq_flags
87438743
=for apidoc_item sv_numne
87448744
=for apidoc_item sv_numne_flags
8745+
=for apidoc_item sv_numge
8746+
=for apidoc_item sv_numge_flags
8747+
=for apidoc_item sv_numgt
8748+
=for apidoc_item sv_numgt_flags
8749+
=for apidoc_item sv_numle
8750+
=for apidoc_item sv_numle_flags
8751+
=for apidoc_item sv_numlt
8752+
=for apidoc_item sv_numlt_flags
87458753

87468754
These return a boolean that is the result of the corresponding numeric
87478755
comparison:
@@ -8760,17 +8768,42 @@ Numeric equality, the same as S<C<$sv1 == $sv2>>.
87608768

87618769
Numeric inequality, the same as S<C<$sv1 != $sv2>>.
87628770

8771+
=item C<sv_numle>
8772+
8773+
=item C<sv_numle_flags>
8774+
8775+
Numeric less than or equal, the same as S<C<$sv1 E<lt>= $sv2>>.
8776+
8777+
=item C<sv_numlt>
8778+
8779+
=item C<sv_numlt_flags>
8780+
8781+
Numeric less than, the same as S<C<$sv1 E<lt> $sv2>>.
8782+
8783+
=item C<sv_numge>
8784+
8785+
=item C<sv_numge_flags>
8786+
8787+
Numeric greater than or equal, the same as S<C<$sv1 E<gt>= $sv2>>.
8788+
8789+
=item C<sv_numgt>
8790+
8791+
=item C<sv_numgt_flags>
8792+
8793+
Numeric greater than, the same as S<C<$sv1 E<gt> $sv2>>.
8794+
87638795
=back
87648796

8765-
Beware that in the presence of overloading C<==> may not be a strict
8766-
inverse of C<!=>.
8797+
Beware that in the presence of overloading the comparisons might not
8798+
have their normal properties, eg. C< sv_numeq(sv1, sv2) > might be
8799+
different to C< !sv_numne(sv1, sv2) >.
87678800

87688801
The non-C<_flags> suffix versions of these functions always perform
87698802
get magic and handle the appropriate type of overloading. See
87708803
L<overload> for details.
87718804

87728805
These each return a boolean indicating if the numbers in the two SV
8773-
arguments are equal or not equal, coercing them to numbers if
8806+
arguments satisfy the given relationship, coercing them to numbers if
87748807
necessary, basically behaving like the Perl code.
87758808

87768809
A NULL SV is treated as C<undef>.
@@ -8813,14 +8846,65 @@ Perl_sv_numne_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
88138846
{
88148847
PERL_ARGS_ASSERT_SV_NUMNE_FLAGS;
88158848

8816-
88178849
SV *result;
88188850
if (UNLIKELY(sv_numcmp_common(&sv1, &sv2, flags, ne_amg, &result)))
88198851
return SvTRUE(result);
88208852

88218853
return do_ncmp(sv1, sv2) != 0;
88228854
}
88238855

8856+
bool
8857+
Perl_sv_numle_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
8858+
{
8859+
PERL_ARGS_ASSERT_SV_NUMLE_FLAGS;
8860+
8861+
SV *result;
8862+
if (UNLIKELY(sv_numcmp_common(&sv1, &sv2, flags, le_amg, &result)))
8863+
return SvTRUE(result);
8864+
8865+
return do_ncmp(sv1, sv2) <= 0;
8866+
}
8867+
8868+
bool
8869+
Perl_sv_numlt_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
8870+
{
8871+
PERL_ARGS_ASSERT_SV_NUMLT_FLAGS;
8872+
8873+
SV *result;
8874+
if (UNLIKELY(sv_numcmp_common(&sv1, &sv2, flags, lt_amg, &result)))
8875+
return SvTRUE(result);
8876+
8877+
return do_ncmp(sv1, sv2) < 0;
8878+
}
8879+
8880+
bool
8881+
Perl_sv_numge_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
8882+
{
8883+
PERL_ARGS_ASSERT_SV_NUMGE_FLAGS;
8884+
8885+
SV *result;
8886+
if (UNLIKELY(sv_numcmp_common(&sv1, &sv2, flags, ge_amg, &result)))
8887+
return SvTRUE(result);
8888+
8889+
I32 cmp = do_ncmp(sv1, sv2);
8890+
8891+
return cmp != 2 && cmp >= 0;
8892+
}
8893+
8894+
bool
8895+
Perl_sv_numgt_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
8896+
{
8897+
PERL_ARGS_ASSERT_SV_NUMGT_FLAGS;
8898+
8899+
SV *result;
8900+
if (UNLIKELY(sv_numcmp_common(&sv1, &sv2, flags, gt_amg, &result)))
8901+
return SvTRUE(result);
8902+
8903+
I32 cmp = do_ncmp(sv1, sv2);
8904+
8905+
return cmp != 2 && cmp > 0;
8906+
}
8907+
88248908
/*
88258909
=for apidoc sv_numcmp
88268910
=for apidoc_item sv_numcmp_flags

sv.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2323,6 +2323,10 @@ Usually accessed via the C<SvPVutf8_nolen> macro.
23232323
#define sv_cmp_locale(sv1, sv2) sv_cmp_locale_flags(sv1, sv2, SV_GMAGIC)
23242324
#define sv_numeq(sv1, sv2) sv_numeq_flags(sv1, sv2, SV_GMAGIC)
23252325
#define sv_numne(sv1, sv2) sv_numne_flags(sv1, sv2, SV_GMAGIC)
2326+
#define sv_numle(sv1, sv2) sv_numle_flags(sv1, sv2, SV_GMAGIC)
2327+
#define sv_numlt(sv1, sv2) sv_numlt_flags(sv1, sv2, SV_GMAGIC)
2328+
#define sv_numge(sv1, sv2) sv_numge_flags(sv1, sv2, SV_GMAGIC)
2329+
#define sv_numgt(sv1, sv2) sv_numgt_flags(sv1, sv2, SV_GMAGIC)
23262330
#define sv_numcmp(sv1, sv2) sv_numcmp_flags(sv1, sv2, SV_GMAGIC)
23272331
#define sv_streq(sv1, sv2) sv_streq_flags(sv1, sv2, SV_GMAGIC)
23282332
#define sv_collxfrm(sv, nxp) sv_collxfrm_flags(sv, nxp, SV_GMAGIC)

0 commit comments

Comments
 (0)