@@ -8707,7 +8707,7 @@ Perl_sv_streq_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
87078707
87088708PERL_STATIC_INLINE bool
87098709S_sv_numcmp_common(pTHX_ SV **sv1, SV **sv2, const U32 flags,
8710- int method, bool *result) {
8710+ int method, SV * *result) {
87118711 if(flags & SV_GMAGIC) {
87128712 if(*sv1)
87138713 SvGETMAGIC(*sv1);
@@ -8721,11 +8721,10 @@ S_sv_numcmp_common(pTHX_ SV **sv1, SV **sv2, const U32 flags,
87218721 if(!*sv2)
87228722 *sv2 = &PL_sv_undef;
87238723
8724- SV *sv_result;
8724+ /* FIXME: do_ncmp doesn't handle "+0" overloads well */
87258725 if(!(flags & SV_SKIP_OVERLOAD) &&
87268726 (SvAMAGIC(*sv1) || SvAMAGIC(*sv2)) &&
8727- (sv_result = amagic_call(*sv1, *sv2, method, 0))) {
8728- *result = SvTRUE(sv_result);
8727+ (*result = amagic_call(*sv1, *sv2, method, 0))) {
87298728 return true;
87308729 }
87318730
@@ -8797,9 +8796,9 @@ Perl_sv_numeq_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
87978796{
87988797 PERL_ARGS_ASSERT_SV_NUMEQ_FLAGS;
87998798
8800- bool result;
8799+ SV * result;
88018800 if (UNLIKELY(sv_numcmp_common(&sv1, &sv2, flags, eq_amg, &result)))
8802- return result;
8801+ return SvTRUE( result) ;
88038802
88048803 return do_ncmp(sv1, sv2) == 0;
88058804}
@@ -8810,13 +8809,86 @@ Perl_sv_numne_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
88108809 PERL_ARGS_ASSERT_SV_NUMNE_FLAGS;
88118810
88128811
8813- bool result;
8812+ SV * result;
88148813 if (UNLIKELY(sv_numcmp_common(&sv1, &sv2, flags, ne_amg, &result)))
8815- return result;
8814+ return SvTRUE( result) ;
88168815
88178816 return do_ncmp(sv1, sv2) != 0;
88188817}
88198818
8819+ /*
8820+ =for apidoc sv_numcmp
8821+ =for apidoc_item sv_numcmp_flags
8822+
8823+ This returns an integer indicating the ordering of the two SV
8824+ arguments, coercing them to numbers if necessary, basically behaving
8825+ like the Perl code S<C<$sv1 <=> $sv2 >>.
8826+
8827+ A NULL SV is treated as C<undef>.
8828+
8829+ This will return one of the following values:
8830+
8831+ =over
8832+
8833+ =item *
8834+
8835+ C<1> - C<sv2> is numerically greater than C<sv1>
8836+
8837+ =item *
8838+
8839+ C<0> - C<sv1> and C<sv2> are numerically equal.
8840+
8841+ =item *
8842+
8843+ C<-1> - C<sv2> is numerically less than C<sv1>
8844+
8845+ =item *
8846+
8847+ C<2> - C<sv1> and C<sv2> are not numerically comparable, probably
8848+ because one of them is C<NaN>, though overloads can extend that.
8849+
8850+ =back
8851+
8852+ C<sv_numcmp> always performs 'get' magic. C<sv_numcmp_flags> performs
8853+ 'get' magic on if C<flags> has the C<SV_GMAGIC> bit set.
8854+
8855+ C<sv_numcmp> always checks for, and if present, handles C<< <=> >>
8856+ overloading. If not present, regular numerical comparison will be
8857+ used instead.
8858+ C<sv_numcmp_flags> normally does the same, but if the
8859+ C<SV_SKIP_OVERLOAD> bit is set in C<flags> any C<< <=> >> overloading
8860+ is ignored and a regular numerical comparison is done instead.
8861+
8862+ =cut
8863+ */
8864+
8865+ #define SANE_ORDERING_RESULT(val) \
8866+ ((val) < 0 ? -1 : (val) > 0 ? 1 : 0)
8867+
8868+ I32
8869+ Perl_sv_numcmp_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
8870+ {
8871+ PERL_ARGS_ASSERT_SV_NUMCMP_FLAGS;
8872+
8873+ SV *result;
8874+ if (UNLIKELY(sv_numcmp_common(&sv1, &sv2, flags, ncmp_amg, &result))) {
8875+ /* Similar to what sort() does in amagic_ncmp() */
8876+ if (SvIOK(result) && !SvIsUV(result)) {
8877+ IV i = SvIVX(result);
8878+ return SANE_ORDERING_RESULT(i);
8879+ }
8880+ else if (!SvOK(result)) {
8881+ return 2;
8882+ }
8883+ else {
8884+ NV nv = SvNV(result);
8885+ return SANE_ORDERING_RESULT(nv);
8886+ }
8887+ }
8888+
8889+ return do_ncmp(sv1, sv2);
8890+ }
8891+
88208892/*
88218893=for apidoc sv_cmp
88228894=for apidoc_item sv_cmp_flags
0 commit comments