Skip to content

Commit

Permalink
sv.c: add Perl_sv_grow_fresh & Perl_sv_setvpn_fresh
Browse files Browse the repository at this point in the history
  • Loading branch information
richardleach committed May 26, 2021
1 parent 2583ef6 commit 759ff77
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 0 deletions.
2 changes: 2 additions & 0 deletions embed.fnc
Original file line number Diff line number Diff line change
Expand Up @@ -1848,6 +1848,7 @@ poxX |void |sv_free2 |NN SV *const sv|const U32 refcnt
pd |void |sv_free_arenas
Apd |char* |sv_gets |NN SV *const sv|NN PerlIO *const fp|I32 append
Cpd |char* |sv_grow |NN SV *const sv|STRLEN newlen
Cpd |char* |sv_grow_fresh |NN SV *const sv|STRLEN newlen
Apd |void |sv_inc |NULLOK SV *const sv
Apd |void |sv_inc_nomg |NULLOK SV *const sv
ApMdb |void |sv_insert |NN SV *const bigstr|const STRLEN offset \
Expand Down Expand Up @@ -1907,6 +1908,7 @@ Apd |SV* |sv_setref_pvn |NN SV *const rv|NULLOK const char *const classname \
|NN const char *const pv|const STRLEN n
Apd |void |sv_setpv |NN SV *const sv|NULLOK const char *const ptr
Apd |void |sv_setpvn |NN SV *const sv|NULLOK const char *const ptr|const STRLEN len
Apd |void |sv_setpvn_fresh|NN SV *const sv|NULLOK const char *const ptr|const STRLEN len
Apd |char *|sv_setpv_bufsize|NN SV *const sv|const STRLEN cur|const STRLEN len
Xp |void |sv_sethek |NN SV *const sv|NULLOK const HEK *const hek
ApMdb |void |sv_setsv |NN SV *dsv|NULLOK SV *ssv
Expand Down
2 changes: 2 additions & 0 deletions embed.h
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,7 @@
#define sv_get_backrefs Perl_sv_get_backrefs
#define sv_gets(a,b,c) Perl_sv_gets(aTHX_ a,b,c)
#define sv_grow(a,b) Perl_sv_grow(aTHX_ a,b)
#define sv_grow_fresh(a,b) Perl_sv_grow_fresh(aTHX_ a,b)
#define sv_inc(a) Perl_sv_inc(aTHX_ a)
#define sv_inc_nomg(a) Perl_sv_inc_nomg(aTHX_ a)
#define sv_insert_flags(a,b,c,d,e,f) Perl_sv_insert_flags(aTHX_ a,b,c,d,e,f)
Expand Down Expand Up @@ -681,6 +682,7 @@
#define sv_setpviv_mg(a,b) Perl_sv_setpviv_mg(aTHX_ a,b)
#endif
#define sv_setpvn(a,b,c) Perl_sv_setpvn(aTHX_ a,b,c)
#define sv_setpvn_fresh(a,b,c) Perl_sv_setpvn_fresh(aTHX_ a,b,c)
#define sv_setpvn_mg(a,b,c) Perl_sv_setpvn_mg(aTHX_ a,b,c)
#define sv_setref_iv(a,b,c) Perl_sv_setref_iv(aTHX_ a,b,c)
#define sv_setref_nv(a,b,c) Perl_sv_setref_nv(aTHX_ a,b,c)
Expand Down
6 changes: 6 additions & 0 deletions proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -3492,6 +3492,9 @@ PERL_CALLCONV char* Perl_sv_gets(pTHX_ SV *const sv, PerlIO *const fp, I32 appen
PERL_CALLCONV char* Perl_sv_grow(pTHX_ SV *const sv, STRLEN newlen);
#define PERL_ARGS_ASSERT_SV_GROW \
assert(sv)
PERL_CALLCONV char* Perl_sv_grow_fresh(pTHX_ SV *const sv, STRLEN newlen);
#define PERL_ARGS_ASSERT_SV_GROW_FRESH \
assert(sv)
PERL_CALLCONV void Perl_sv_inc(pTHX_ SV *const sv);
#define PERL_ARGS_ASSERT_SV_INC
PERL_CALLCONV void Perl_sv_inc_nomg(pTHX_ SV *const sv);
Expand Down Expand Up @@ -3737,6 +3740,9 @@ PERL_CALLCONV void Perl_sv_setpviv_mg(pTHX_ SV *const sv, const IV iv)
PERL_CALLCONV void Perl_sv_setpvn(pTHX_ SV *const sv, const char *const ptr, const STRLEN len);
#define PERL_ARGS_ASSERT_SV_SETPVN \
assert(sv)
PERL_CALLCONV void Perl_sv_setpvn_fresh(pTHX_ SV *const sv, const char *const ptr, const STRLEN len);
#define PERL_ARGS_ASSERT_SV_SETPVN_FRESH \
assert(sv)
PERL_CALLCONV void Perl_sv_setpvn_mg(pTHX_ SV *const sv, const char *const ptr, const STRLEN len);
#define PERL_ARGS_ASSERT_SV_SETPVN_MG \
assert(sv); assert(ptr)
Expand Down
83 changes: 83 additions & 0 deletions sv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1625,6 +1625,59 @@ Perl_sv_grow(pTHX_ SV *const sv, STRLEN newlen)
return s;
}

/*
=for apidoc sv_grow_fresh
A cut-down version of sv_grow intended only for when sv is a freshly-minted
SVt_PV. i.e. sv has the default flags, has never been any other type, and
does not have an existing string. Basically, just assigns a char* buffer.
Returns a pointer to the character buffer.
=cut
*/


char *
Perl_sv_grow_fresh(pTHX_ SV *const sv, STRLEN newlen)
{
char *s;

PERL_ARGS_ASSERT_SV_GROW_FRESH;

assert(SvTYPE(sv) == SVt_PV);
assert(!SvROK(sv));
assert(!SvOOK(sv));
assert(!SvIsCOW(sv));
assert(!SvLEN(sv));
assert(!SvCUR(sv));

#ifdef PERL_COPY_ON_WRITE
/* the new COW scheme uses SvPVX(sv)[SvLEN(sv)-1] (if spare)
* to store the COW count. So in general, allocate one more byte than
* asked for, to make it likely this byte is always spare: and thus
* make more strings COW-able.
*
* Only increment if the allocation isn't MEM_SIZE_MAX,
* otherwise it will wrap to 0.
*/
if ( newlen != MEM_SIZE_MAX )
newlen++;
#endif

/* 10 is a longstanding, hardcoded minimum length in sv_grow. */
/* Just doing the same here for consistency. */
if (newlen < 10)
newlen = 10;

s = (char*)safemalloc(newlen);
SvPV_set(sv, s);

/* No PERL_UNWARANTED_CHUMMINESS_WITH_MALLOC here, since many strings */
/* will never be grown once set. Let the real sv_grow worry about that. */
SvLEN_set(sv, newlen);
return s;
}

/*
=for apidoc sv_setiv
=for apidoc_item sv_setiv_mg
Expand Down Expand Up @@ -4907,6 +4960,7 @@ Perl_sv_setpv_bufsize(pTHX_ SV *const sv, const STRLEN cur, const STRLEN len)

/*
=for apidoc sv_setpvn
=for apidoc sv_setpvn_fresh
=for apidoc_item sv_setpvn_mg
These copy a string (possibly containing embedded C<NUL> characters) into an
Expand All @@ -4921,6 +4975,9 @@ They differ only in that:
C<sv_setpvn> does not handle 'set' magic; C<sv_setpvn_mg> does.
C<sv_setpvn_fresh> is a cut-down alternative to C<sv_setpvn>, intended ONLY
to be used with a fresh sv that has been upgraded to a SVt_PV.
=cut
*/

Expand Down Expand Up @@ -4965,6 +5022,32 @@ Perl_sv_setpvn_mg(pTHX_ SV *const sv, const char *const ptr, const STRLEN len)
SvSETMAGIC(sv);
}

void
Perl_sv_setpvn_fresh(pTHX_ SV *const sv, const char *const ptr, const STRLEN len)
{
char *dptr;

PERL_ARGS_ASSERT_SV_SETPVN_FRESH;
assert(SvTYPE(sv) == SVt_PV);
assert(!SvTHINKFIRST(sv));
assert(!isGV_with_GP(sv));

if (ptr) {
const IV iv = len;
/* len is STRLEN which is unsigned, need to copy to signed */
if (iv < 0)
Perl_croak(aTHX_ "panic: sv_setpvn_fresh called with negative strlen %"
IVdf, iv);

dptr = sv_grow_fresh(sv, len + 1);
Move(ptr,dptr,len,char);
dptr[len] = '\0';
SvCUR_set(sv, len);
SvPOK_on(sv);
SvTAINT(sv);
}
}

/*
=for apidoc sv_setpv
=for apidoc_item sv_setpv_mg
Expand Down

0 comments on commit 759ff77

Please sign in to comment.