Skip to content

Commit 6fcf935

Browse files
committed
Define new API for accessing PERL_MAGIC_vstring
Adds two new API functions to abstract out applying or querying the `PERL_MAGIC_vstring` annotation, used to create vstring values. Code can now use these API functions without needing to be aware of the inner details involved in how the magic currently works.
1 parent a9ad65a commit 6fcf935

File tree

9 files changed

+138
-8
lines changed

9 files changed

+138
-8
lines changed

MANIFEST

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5216,6 +5216,7 @@ ext/XS-APItest/t/utf8_warn08.t Tests for code in utf8.c
52165216
ext/XS-APItest/t/utf8_warn09.t Tests for code in utf8.c
52175217
ext/XS-APItest/t/utf8_warn_base.pl Tests for code in utf8.c
52185218
ext/XS-APItest/t/valid_identifier.t XS::APItest: tests for valid_identifier_sv()
5219+
ext/XS-APItest/t/vstring.t XS::APItest: tests for sv_vstring_*() API
52195220
ext/XS-APItest/t/weaken.t XS::APItest: tests for sv_rvweaken() and sv_get_backrefs()
52205221
ext/XS-APItest/t/whichsig.t XS::APItest: tests for whichsig() and variants
52215222
ext/XS-APItest/t/win32.t Test Win32 specific APIs

embed.fnc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3600,6 +3600,12 @@ Adp |void |sv_vsetpvfn |NN SV * const sv \
36003600
|NULLOK SV ** const svargs \
36013601
|const Size_t sv_count \
36023602
|NULLOK bool * const maybe_tainted
3603+
Adp |bool |sv_vstring_get |NN SV * const sv \
3604+
|NULLOK const char **pvp \
3605+
|NULLOK STRLEN *lenp
3606+
Adp |void |sv_vstring_set |NN SV * const sv \
3607+
|NN const char *pv \
3608+
|STRLEN const len
36033609
Cipx |void |switch_argstack|NN AV *to
36043610
Adp |void |switch_to_global_locale
36053611
Adp |bool |sync_locale

embed.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,8 @@
848848
# define sv_vsetpvf(a,b,c) Perl_sv_vsetpvf(aTHX_ a,b,c)
849849
# define sv_vsetpvf_mg(a,b,c) Perl_sv_vsetpvf_mg(aTHX_ a,b,c)
850850
# define sv_vsetpvfn(a,b,c,d,e,f,g) Perl_sv_vsetpvfn(aTHX_ a,b,c,d,e,f,g)
851+
# define sv_vstring_get(a,b,c) Perl_sv_vstring_get(aTHX_ a,b,c)
852+
# define sv_vstring_set(a,b,c) Perl_sv_vstring_set(aTHX_ a,b,c)
851853
# define switch_argstack(a) Perl_switch_argstack(aTHX_ a)
852854
# define switch_to_global_locale() Perl_switch_to_global_locale(aTHX)
853855
# define sync_locale() Perl_sync_locale(aTHX)

ext/XS-APItest/APItest.xs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8200,3 +8200,31 @@ get_savestack_ix()
82008200
RETVAL = PL_savestack_ix;
82018201
OUTPUT:
82028202
RETVAL
8203+
8204+
MODULE = XS::APItest PACKAGE = XS::APItest::vstring
8205+
8206+
bool
8207+
SvVOK(SV *sv)
8208+
8209+
SV *
8210+
sv_vstring_get(SV *sv)
8211+
CODE:
8212+
{
8213+
const char *vstr_pv;
8214+
STRLEN vstr_len;
8215+
if(sv_vstring_get(sv, &vstr_pv, &vstr_len))
8216+
RETVAL = newSVpvn(vstr_pv, vstr_len);
8217+
else
8218+
RETVAL = &PL_sv_undef;
8219+
}
8220+
OUTPUT:
8221+
RETVAL
8222+
8223+
void
8224+
sv_vstring_set(SV *sv, SV *newstr)
8225+
CODE:
8226+
{
8227+
STRLEN len;
8228+
const char *pv = SvPV(newstr, len);
8229+
sv_vstring_set(sv, pv, len);
8230+
}

ext/XS-APItest/t/vstring.t

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!perl
2+
3+
use Test::More tests => 5;
4+
use XS::APItest;
5+
6+
{
7+
my $vstr = v1.23.456;
8+
ok SvVOK($vstr), '$vstr has SvVOK';
9+
is sv_vstring_get($vstr), "v1.23.456", 'sv_vstring_get()';
10+
}
11+
12+
{
13+
my $sv = "plain";
14+
sv_vstring_set($sv, "v7.89");
15+
ok SvVOK($sv), '$sv has SvVOK after sv_vstring_set()';
16+
is sv_vstring_get($sv), "v7.89", '$sv has stored vstring';
17+
18+
sv_vstring_set($sv, "v9.87");
19+
is sv_vstring_get($sv), "v9.87", 'sv_vstring_set() can update stored vstring';
20+
}

pod/perldelta.pod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,14 @@ API functions avoids XS modules needing to know about or interact directly
363363
with the way this position is currently stored, which involves the
364364
C<PERL_MAGIC_regex_global> magic type.
365365

366+
=item *
367+
368+
Two new API functions have been added to interact with SVs that behave as
369+
vstrings. These are C<sv_vstring_get()> and C<sv_vstring_set()>. Using
370+
these API functions avoids XS modules needing to know about or interact
371+
directly with the way this information is currently stored, which involves
372+
the C<PERL_MAGIC_vstring> magic type.
373+
366374
=back
367375

368376
=head1 Selected Bug Fixes

proto.h

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sv.c

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4730,12 +4730,10 @@ Perl_sv_setsv_flags(pTHX_ SV *dsv, SV* ssv, const I32 flags)
47304730
}
47314731
SvFLAGS(dsv) |= sflags & (SVf_IOK|SVp_IOK|SVf_NOK|SVp_NOK|SVf_UTF8);
47324732
{
4733-
const MAGIC * const smg = SvVSTRING_mg(ssv);
4734-
if (smg) {
4735-
sv_magic(dsv, NULL, PERL_MAGIC_vstring,
4736-
smg->mg_ptr, smg->mg_len);
4737-
SvRMAGICAL_on(dsv);
4738-
}
4733+
const char *vstr_pv;
4734+
STRLEN vstr_len;
4735+
if (sv_vstring_get(ssv, &vstr_pv, &vstr_len))
4736+
sv_vstring_set(dsv, vstr_pv, vstr_len);
47394737
}
47404738
}
47414739
else if (sflags & (SVp_IOK|SVp_NOK)) {
@@ -17878,6 +17876,64 @@ Perl_sv_regex_global_pos_clear(pTHX_ SV *sv)
1787817876
mg->mg_len = -1;
1787917877
}
1788017878

17879+
/*
17880+
=for apidoc sv_vstring_get
17881+
17882+
If the given SV has vstring magic, stores the string pointer and length into
17883+
the variables addressed by C<pvp> and C<lenp>, and returns true. If not,
17884+
returns false.
17885+
17886+
If a pointer is returned to the caller in the C<pvp> variable, it will point
17887+
to memory owned by the SV itself. The caller is not responsible for freeing
17888+
it after this call, though it will not remain valid for longer than the
17889+
lifetime of the SV itself. The caller should take a copy of it if it needs
17890+
to be accessed after this time.
17891+
17892+
=cut
17893+
*/
17894+
17895+
bool
17896+
Perl_sv_vstring_get(pTHX_ SV * const sv, const char **pvp, STRLEN *lenp)
17897+
{
17898+
PERL_ARGS_ASSERT_SV_VSTRING_GET;
17899+
17900+
MAGIC *mg = SvVSTRING_mg(sv);
17901+
if(!mg) return false;
17902+
17903+
if(pvp) *pvp = mg->mg_ptr;
17904+
if(lenp) *lenp = mg->mg_len;
17905+
return true;
17906+
}
17907+
17908+
/*
17909+
=for apidoc sv_vstring_set
17910+
17911+
Applies vstring magic to the given SV, storing the string given by C<pv> for
17912+
C<len> bytes into it. If the SV already had vstring magic, the previous
17913+
stored string is freed and replaced.
17914+
17915+
=cut
17916+
*/
17917+
17918+
void
17919+
Perl_sv_vstring_set(pTHX_ SV * const sv, const char *pv, STRLEN const len)
17920+
{
17921+
PERL_ARGS_ASSERT_SV_VSTRING_SET;
17922+
17923+
MAGIC *mg;
17924+
if((mg = SvVSTRING_mg(sv))) {
17925+
char *was_ptr = mg->mg_ptr;
17926+
mg->mg_ptr = savepvn(pv, len);
17927+
mg->mg_len = len;
17928+
17929+
Safefree(was_ptr);
17930+
}
17931+
else {
17932+
sv_magic(sv, NULL, PERL_MAGIC_vstring, pv, len);
17933+
SvRMAGICAL_on(sv);
17934+
}
17935+
}
17936+
1788117937
/*
1788217938
* ex: set ts=8 sts=4 sw=4 et:
1788317939
*/

toke.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13353,8 +13353,7 @@ Perl_scan_vstring(pTHX_ const char *s, const char *const e, SV *sv)
1335313353
pos++;
1335413354
}
1335513355
SvPOK_on(sv);
13356-
sv_magic(sv,NULL,PERL_MAGIC_vstring,(const char*)start, pos-start);
13357-
SvRMAGICAL_on(sv);
13356+
sv_vstring_set(sv, start, pos-start);
1335813357
}
1335913358
return (char *)s;
1336013359
}

0 commit comments

Comments
 (0)