Provide a new flag for sv_usepvn_flags, SV_HAS_TRAILING_NUL, which
Nicholas Clark [Sun, 16 Apr 2006 11:35:38 +0000 (11:35 +0000)]
signals that the buffer passed in is already well-formed for use as
SvPVX (i.e. it is followed by a trailing NUL), and hence the realloc()
to add a NUL can be skipped.

p4raw-id: //depot/perl@27841

pp.c
sv.c
sv.h

diff --git a/pp.c b/pp.c
index a1f51aa..8914545 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -2458,9 +2458,9 @@ PP(pp_complement)
                  p = uvchr_to_utf8_flags(p, ~c, UNICODE_ALLOW_ANY);
              }
              *p = '\0';
-             sv_setpvn(TARG, (char*)result, targlen);
+             sv_usepvn_flags(TARG, (char*)result, targlen,
+                             SV_HAS_TRAILING_NUL);
              SvUTF8_on(TARG);
-             Safefree(result);
          }
          else {
              U8 *result;
@@ -2474,9 +2474,8 @@ PP(pp_complement)
                  *p++ = ~c;
              }
              *p = '\0';
-             sv_setpvn(TARG, (char*)result, nchar);
+             sv_usepvn_flags(TARG, (char*)result, nchar, SV_HAS_TRAILING_NUL);
              SvUTF8_off(TARG);
-             Safefree(result);
          }
          SETs(TARG);
          RETURN;
diff --git a/sv.c b/sv.c
index 85290bb..247ab31 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -3890,12 +3890,16 @@ Perl_sv_setpv_mg(pTHX_ register SV *sv, register const char *ptr)
 Tells an SV to use C<ptr> to find its string value.  Normally the
 string is stored inside the SV but sv_usepvn allows the SV to use an
 outside string.  The C<ptr> should point to memory that was allocated
-by C<malloc>.  The string length, C<len>, must be supplied.  This
-function will realloc (i.e. move) the memory pointed to by C<ptr>,
+by C<malloc>.  The string length, C<len>, must be supplied.  By default
+this function will realloc (i.e. move) the memory pointed to by C<ptr>,
 so that pointer should not be freed or used by the programmer after
 giving it to sv_usepvn, and neither should any pointers from "behind"
-that pointer (e.g. ptr + 1) be used.  If C<flags> & SV_SMAGIC is true, will
-call SvSETMAGIC.
+that pointer (e.g. ptr + 1) be used.
+
+If C<flags> & SV_SMAGIC is true, will call SvSETMAGIC. If C<flags> &
+SV_HAS_TRAILING_NUL is true, then C<ptr[len]> must be NUL, and the realloc
+I<may> be skipped. (i.e. the buffer is actually at least 1 byte longer than
+C<len>, and already meets the requirements for storing in C<SvPVX>)
 
 =cut
 */
@@ -3916,7 +3920,8 @@ Perl_sv_usepvn_flags(pTHX_ SV *sv, char *ptr, STRLEN len, U32 flags)
     if (SvPVX_const(sv))
        SvPV_free(sv);
 
-    allocate = PERL_STRLEN_ROUNDUP(len + 1);
+    allocate = (flags & SV_HAS_TRAILING_NUL)
+       ? len : PERL_STRLEN_ROUNDUP(len + 1);
 #ifdef DEBUGGING
     {
        /* Force a move to shake out bugs in callers.  */
@@ -3927,12 +3932,16 @@ Perl_sv_usepvn_flags(pTHX_ SV *sv, char *ptr, STRLEN len, U32 flags)
        ptr = new_ptr;
     }
 #else
-    ptr = saferealloc (ptr, allocate);
+    if (!(flags & SV_HAS_TRAILING_NUL)) {
+       ptr = saferealloc (ptr, allocate);
+    }
 #endif
     SvPV_set(sv, ptr);
     SvCUR_set(sv, len);
     SvLEN_set(sv, allocate);
-    *SvEND(sv) = '\0';
+    if (!(flags & SV_HAS_TRAILING_NUL)) {
+       *SvEND(sv) = '\0';
+    }
     (void)SvPOK_only_UTF8(sv);         /* validate pointer */
     SvTAINT(sv);
     if (flags & SV_SMAGIC)
diff --git a/sv.h b/sv.h
index e887497..b6d4b14 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -1637,6 +1637,7 @@ Like C<sv_catsv> but doesn't process magic.
 #define SV_CONST_RETURN                32
 #define SV_MUTABLE_RETURN      64
 #define SV_SMAGIC              128
+#define SV_HAS_TRAILING_NUL    256
 
 #define sv_unref(sv)           sv_unref_flags(sv, 0)
 #define sv_force_normal(sv)    sv_force_normal_flags(sv, 0)