Better sv_2pv_flags implementation (avoid writing to n_a)
Nicholas Clark [Wed, 8 Jun 2005 08:49:32 +0000 (08:49 +0000)]
p4raw-id: //depot/perl@24749

sv.c

diff --git a/sv.c b/sv.c
index 709b99d..de411a5 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -3394,22 +3394,18 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
     SV *tsv, *origsv;
     char tbuf[64];     /* Must fit sprintf/Gconvert of longest IV/NV */
     char *tmpbuf = tbuf;
-    STRLEN n_a;
-
-    if (!lp) {
-       /* Saves needing to do lots of if (!lp) checks below  */
-       lp = &n_a;
-    }
 
     if (!sv) {
-       *lp = 0;
+       if (lp)
+           *lp = 0;
        return (char *)"";
     }
     if (SvGMAGICAL(sv)) {
        if (flags & SV_GMAGIC)
            mg_get(sv);
        if (SvPOKp(sv)) {
-           *lp = SvCUR(sv);
+           if (lp)
+               *lp = SvCUR(sv);
            if (flags & SV_MUTABLE_RETURN)
                return SvPVX_mutable(sv);
            if (flags & SV_CONST_RETURN)
@@ -3434,7 +3430,8 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
                if (ckWARN(WARN_UNINITIALIZED) && !PL_localizing)
                    report_uninit(sv);
            }
-            *lp = 0;
+           if (lp)
+               *lp = 0;
             return (char *)"";
         }
     }
@@ -3444,7 +3441,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
             register const char *typestr;
             if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,string)) &&
                 (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) {
-                char *pv = SvPV(tmpstr, *lp);
+                char *pv = lp ? SvPV(tmpstr, *lp) : SvPV_nolen(tmpstr);
                 if (SvUTF8(tmpstr))
                     SvUTF8_on(sv);
                 else
@@ -3539,7 +3536,8 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
                            SvUTF8_on(origsv);
                        else
                            SvUTF8_off(origsv);
-                       *lp = mg->mg_len;
+                       if (lp)
+                           *lp = mg->mg_len;
                        return mg->mg_ptr;
                    }
                                        /* Fall through */
@@ -3574,13 +3572,15 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
                    Perl_sv_setpvf(aTHX_ tsv, "%s(0x%"UVxf")", typestr, PTR2UV(sv));
                goto tokensaveref;
            }
-           *lp = strlen(typestr);
+           if (lp)
+               *lp = strlen(typestr);
            return (char *)typestr;
        }
        if (SvREADONLY(sv) && !SvOK(sv)) {
            if (ckWARN(WARN_UNINITIALIZED))
                report_uninit(sv);
-           *lp = 0;
+           if (lp)
+               *lp = 0;
            return (char *)"";
        }
     }
@@ -3640,14 +3640,19 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
        if (ckWARN(WARN_UNINITIALIZED)
            && !PL_localizing && !(SvFLAGS(sv) & SVs_PADTMP))
            report_uninit(sv);
+       if (lp)
        *lp = 0;
        if (SvTYPE(sv) < SVt_PV)
            /* Typically the caller expects that sv_any is not NULL now.  */
            sv_upgrade(sv, SVt_PV);
        return (char *)"";
     }
-    *lp = s - SvPVX_const(sv);
-    SvCUR_set(sv, *lp);
+    {
+       STRLEN len = s - SvPVX_const(sv);
+       if (lp) 
+           *lp = len;
+       SvCUR_set(sv, len);
+    }
     SvPOK_on(sv);
     DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%"UVxf" 2pv(%s)\n",
                          PTR2UV(sv),SvPVX_const(sv)));
@@ -3665,7 +3670,8 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
        if (!tsv)
            tsv = newSVpv(tmpbuf, 0);
        sv_2mortal(tsv);
-       *lp = SvCUR(tsv);
+       if (lp)
+           *lp = SvCUR(tsv);
        return SvPVX(tsv);
     }
     else {
@@ -3689,7 +3695,8 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
        }
 #endif
        SvUPGRADE(sv, SVt_PV);
-       *lp = len;
+       if (lp)
+           *lp = len;
        s = SvGROW(sv, len + 1);
        SvCUR_set(sv, len);
        SvPOKp_on(sv);