diff options
author | Chip Salzenberg <chip@pobox.com> | 2011-08-11 23:44:28 -0700 |
---|---|---|
committer | Chip Salzenberg <chip@pobox.com> | 2011-08-11 23:44:28 -0700 |
commit | cef2aeb153dc12c2124af229e71c3cfb2f8b0cb3 (patch) | |
tree | 2c4d1b511cf318ef67ee1169ca455416214773e2 | |
parent | eb796c7f1a47acbd996034731639c1bb76e31a19 (diff) | |
download | perl-cef2aeb153dc12c2124af229e71c3cfb2f8b0cb3.tar.gz |
Real working isnumber and isstring
-rw-r--r-- | cpan/List-Util/ListUtil.xs | 24 | ||||
-rw-r--r-- | cpan/List-Util/lib/Scalar/Util.pm | 36 | ||||
-rw-r--r-- | dist/Data-Dumper/Dumper.xs | 2 | ||||
-rw-r--r-- | sv.c | 47 | ||||
-rw-r--r-- | sv.h | 5 |
5 files changed, 72 insertions, 42 deletions
diff --git a/cpan/List-Util/ListUtil.xs b/cpan/List-Util/ListUtil.xs index 7da9b959d1..efe89ebf7a 100644 --- a/cpan/List-Util/ListUtil.xs +++ b/cpan/List-Util/ListUtil.xs @@ -526,6 +526,30 @@ CODE: croak("vstrings are not implemented in this release of perl"); #endif +void +isstring(sv) + SV *sv +PROTOTYPE: $ +CODE: +#if PERL_VERSION > 15 || (PERL_VERSION == 15 && PERL_SUBVERSION >= 1) + ST(0) = boolSV(SvIsSTRING(sv)); + XSRETURN(1); +#else + croak("scalar types are not implemented in this release of perl"); +#endif + +void +isnumber(sv) + SV *sv +PROTOTYPE: $ +CODE: +#if PERL_VERSION > 15 || (PERL_VERSION == 15 && PERL_SUBVERSION >= 1) + ST(0) = boolSV(SvIsNUMBER(sv)); + XSRETURN(1); +#else + croak("scalar types are not implemented in this release of perl"); +#endif + int looks_like_number(sv) SV *sv diff --git a/cpan/List-Util/lib/Scalar/Util.pm b/cpan/List-Util/lib/Scalar/Util.pm index 24138ca4d8..1e104ecc01 100644 --- a/cpan/List-Util/lib/Scalar/Util.pm +++ b/cpan/List-Util/lib/Scalar/Util.pm @@ -12,7 +12,7 @@ require Exporter; require List::Util; # List::Util loads the XS @ISA = qw(Exporter); -@EXPORT_OK = qw(blessed dualvar reftype weaken isweak tainted readonly openhandle refaddr isvstring looks_like_number set_prototype); +@EXPORT_OK = qw(blessed dualvar reftype weaken isweak tainted readonly openhandle refaddr isvstring isstring isnumber looks_like_number set_prototype); $VERSION = "1.23"; $VERSION = eval $VERSION; @@ -20,7 +20,7 @@ unless (defined &dualvar) { # Load Pure Perl version if XS not loaded require Scalar::Util::PP; Scalar::Util::PP->import; - push @EXPORT_FAIL, qw(weaken isweak dualvar isvstring set_prototype); + push @EXPORT_FAIL, qw(weaken isweak dualvar isvstring isstring isnumber set_prototype); } sub export_fail { @@ -42,6 +42,11 @@ sub export_fail { Carp::croak("Vstrings are not implemented in the version of perl"); } + if (grep { /^(isstring|isnumber)$/ } @_ ) { + require Carp; + Carp::croak("Scalar types are not implemented in the version of perl"); + } + @_; } @@ -74,7 +79,7 @@ Scalar::Util - A selection of general-utility scalar subroutines =head1 SYNOPSIS use Scalar::Util qw(blessed dualvar isweak readonly refaddr reftype tainted - weaken isvstring looks_like_number set_prototype); + weaken isvstring isstring isnumber looks_like_number set_prototype); # and other useful utils appearing below =head1 DESCRIPTION @@ -120,6 +125,31 @@ If EXPR is a scalar which was coded as a vstring the result is true. $fmt = isvstring($vs) ? "%vd" : "%s"; #true printf($fmt,$vs); +=item isstring EXPR + +If EXPR is a scalar with a value that is originally a string -- that is, +NOT the result of merely stringifying a numeric value -- the result is true. +NOTE: This function may return a false positive on globs; this should change. + + $s = "1"; + $n = 1; + isstring $s; #true + isstring $n; #false + $foo = $n . ''; + isstring $n; #still false + +=item isnumber ExPR + +If EXPR is a scalar with a value that is originally a number, even if that +value has been incidentally stringified, the result is true. + + $s = "1"; + $n = 1; + isnumber $s; #false + isnumber $n; #true + $foo = $n . ''; + isnumber $n; #still true + =item isweak EXPR If EXPR is a scalar which is a weak reference the result is true. diff --git a/dist/Data-Dumper/Dumper.xs b/dist/Data-Dumper/Dumper.xs index 2c249db9dd..14224bde67 100644 --- a/dist/Data-Dumper/Dumper.xs +++ b/dist/Data-Dumper/Dumper.xs @@ -1151,7 +1151,7 @@ Data_Dumper_Dumpxs(href, ...) else (void)SvOK_off(name); - if (SvPOK(name)) { + if (SvPOK(name) || SvPOKp(name)) { if ((SvPVX_const(name))[0] == '*') { if (SvROK(val)) { switch (SvTYPE(SvRV(val))) { @@ -1165,42 +1165,9 @@ Perl_sv_upgrade(pTHX_ register SV *const sv, svtype new_type) old_body = SvANY(sv); /* Copying structures onto other structures that have been neatly zeroed - has a subtle gotcha. Consider XPVMG - - +------+------+------+------+------+-------+-------+ - | NV | CUR | LEN | IV | MAGIC | STASH | - +------+------+------+------+------+-------+-------+ - 0 4 8 12 16 20 24 28 - - where NVs are aligned to 8 bytes, so that sizeof that structure is - actually 32 bytes long, with 4 bytes of padding at the end: - - +------+------+------+------+------+-------+-------+------+ - | NV | CUR | LEN | IV | MAGIC | STASH | ??? | - +------+------+------+------+------+-------+-------+------+ - 0 4 8 12 16 20 24 28 32 - - so what happens if you allocate memory for this structure: - - +------+------+------+------+------+-------+-------+------+------+... - | NV | CUR | LEN | IV | MAGIC | STASH | GP | NAME | - +------+------+------+------+------+-------+-------+------+------+... - 0 4 8 12 16 20 24 28 32 36 - - zero it, then copy sizeof(XPVMG) bytes on top of it? Not quite what you - expect, because you copy the area marked ??? onto GP. Now, ??? may have - started out as zero once, but it's quite possible that it isn't. So now, - rather than a nicely zeroed GP, you have it pointing somewhere random. - Bugs ensue. - - (In fact, GP ends up pointing at a previous GP structure, because the - principle cause of the padding in XPVMG getting garbage is a copy of - sizeof(XPVMG) bytes from a XPVGV structure in sv_unglob. Right now - this happens to be moot because XPVGV has been re-ordered, with GP - no longer after STASH) - - So we are careful and work out the size of used parts of all the - structures. */ + has a subtle gotcha. The original structure may have unused padding + at the end, which the new structure assigns a meaning to. So we are + careful and work out the size of used parts of all the structures. */ switch (old_type) { case SVt_NULL: @@ -2716,6 +2683,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags { dVAR; register char *s; + bool priv = FALSE; if (!sv) { if (lp) @@ -2923,6 +2891,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags Move(ptr, s, len, char); s += len; *s = '\0'; + priv = TRUE; } else if (SvNOKp(sv)) { if (SvTYPE(sv) < SVt_PVNV) @@ -2944,6 +2913,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags if (s[-1] == '.') *--s = '\0'; #endif + priv = TRUE; } else { if (isGV_with_GP(sv)) { @@ -2987,7 +2957,10 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags *lp = len; SvCUR_set(sv, len); } - SvPOK_on(sv); + if (priv) + SvPOKp_on(sv); + else + SvPOK_on(sv); DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%"UVxf" 2pv(%s)\n", PTR2UV(sv),SvPVX_const(sv))); if (flags & SV_CONST_RETURN) @@ -52,7 +52,7 @@ typedef enum { SVt_PV, /* 4 */ SVt_PVIV, /* 5 */ SVt_PVNV, /* 6 */ - SVt_PVMG, /* 7 */ + SVt_PVMG, /* 7 - first one with magic and blessing */ SVt_REGEXP, /* 8 */ /* PVBM was here, before BIND replaced it. */ SVt_PVGV, /* 9 */ @@ -736,6 +736,9 @@ Set the actual length of the string which is in the SV. See C<SvIV_set>. #define SvNIOK_off(sv) (SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK| \ SVp_IOK|SVp_NOK|SVf_IVisUV)) +#define SvIsSTRING(sv) ((SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK)) == SVf_POK) +#define SvIsNUMBER(sv) (SvNIOK(sv) && !SvPOK(sv)) + #if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) #define assert_not_ROK(sv) ({assert(!SvROK(sv) || !SvRV(sv));}), #define assert_not_glob(sv) ({assert(!isGV_with_GP(sv));}), |