Skip to content

Commit 80f24f4

Browse files
committed
Add sv_vstring_get() API function and SvVSTRING() wrapper macro
This new function and wrapper macro mean that caller code does not have to directly rely on (or be aware of) the `PERL_MAGIC_vstring` type. The intent of the API now works independently of the current implemention as magic.
1 parent 60e9e3b commit 80f24f4

File tree

10 files changed

+109
-11
lines changed

10 files changed

+109
-11
lines changed

MANIFEST

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

dist/Storable/Storable.xs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,23 @@ typedef STRLEN ntag_t;
296296
#define VSTRING_CROAK() CROAK(("Cannot retrieve vstring in this perl"))
297297
#endif
298298

299+
#ifndef sv_vstring_get
300+
#define sv_vstring_get(sv,lenp) S_sv_vstring_get(aTHX_ sv,lenp)
301+
static const char *S_sv_vstring_get(pTHX_ SV *sv, STRLEN *lenp)
302+
{
303+
MAGIC *mg;
304+
if(!SvMAGICAL(sv) || !(mg = mg_find(sv, PERL_MAGIC_vstring)))
305+
return NULL;
306+
307+
*lenp = mg->mg_len;
308+
return mg->mg_ptr;
309+
}
310+
#endif
311+
312+
#ifndef SvVSTRING
313+
#define SvVSTRING(sv,len) (sv_vstring_get(sv, &(len)))
314+
#endif
315+
299316
#ifdef HvPLACEHOLDERS
300317
#define HAS_RESTRICTED_HASHES
301318
#else
@@ -2583,7 +2600,8 @@ static int store_scalar(pTHX_ stcxt_t *cxt, SV *sv)
25832600

25842601
} else if (flags & (SVp_POK | SVp_NOK | SVp_IOK)) {
25852602
#ifdef SvVOK
2586-
MAGIC *mg;
2603+
const char *vstr_pv;
2604+
STRLEN vstr_len;
25872605
#endif
25882606
UV wlen; /* For 64-bit machines */
25892607

@@ -2597,18 +2615,16 @@ static int store_scalar(pTHX_ stcxt_t *cxt, SV *sv)
25972615
string:
25982616

25992617
#ifdef SvVOK
2600-
if (SvMAGICAL(sv) && (mg = mg_find(sv, 'V'))) {
2618+
if ((vstr_pv = SvVSTRING(sv, vstr_len))) {
26012619
/* The macro passes this by address, not value, and a lot of
26022620
called code assumes that it's 32 bits without checking. */
2603-
const SSize_t len = mg->mg_len;
26042621
/* we no longer accept vstrings over I32_SIZE-1, so don't emit
26052622
them, also, older Storables handle them badly.
26062623
*/
2607-
if (len >= I32_MAX) {
2624+
if (vstr_len >= I32_MAX) {
26082625
CROAK(("vstring too large to freeze"));
26092626
}
2610-
STORE_PV_LEN((const char *)mg->mg_ptr,
2611-
len, SX_VSTRING, SX_LVSTRING);
2627+
STORE_PV_LEN(vstr_pv, vstr_len, SX_VSTRING, SX_LVSTRING);
26122628
}
26132629
#endif
26142630

dist/Storable/lib/Storable.pm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ our @EXPORT_OK = qw(
3030
our ($canonical, $forgive_me);
3131

3232
BEGIN {
33-
our $VERSION = '3.35';
33+
our $VERSION = '3.36';
3434
}
3535

3636
our $recursion_limit;

embed.fnc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3602,6 +3602,9 @@ Adp |void |sv_vsetpvfn |NN SV * const sv \
36023602
|NULLOK SV ** const svargs \
36033603
|const Size_t sv_count \
36043604
|NULLOK bool * const maybe_tainted
3605+
Adp |const char *|sv_vstring_get \
3606+
|NN SV * const sv \
3607+
|NULLOK STRLEN *lenp
36053608
Cipx |void |switch_argstack|NN AV *to
36063609
Adp |void |switch_to_global_locale
36073610
Adp |bool |sync_locale

embed.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,7 @@
849849
# define sv_vsetpvf(a,b,c) Perl_sv_vsetpvf(aTHX_ a,b,c)
850850
# define sv_vsetpvf_mg(a,b,c) Perl_sv_vsetpvf_mg(aTHX_ a,b,c)
851851
# define sv_vsetpvfn(a,b,c,d,e,f,g) Perl_sv_vsetpvfn(aTHX_ a,b,c,d,e,f,g)
852+
# define sv_vstring_get(a,b) Perl_sv_vstring_get(aTHX_ a,b)
852853
# define switch_argstack(a) Perl_switch_argstack(aTHX_ a)
853854
# define switch_to_global_locale() Perl_switch_to_global_locale(aTHX)
854855
# define sync_locale() Perl_sync_locale(aTHX)

ext/XS-APItest/APItest.xs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8200,3 +8200,22 @@ 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+
SvVSTRING(SV *sv)
8211+
CODE:
8212+
{
8213+
const char *vstr_pv;
8214+
STRLEN vstr_len;
8215+
if((vstr_pv = SvVSTRING(sv, vstr_len)))
8216+
RETVAL = newSVpvn(vstr_pv, vstr_len);
8217+
else
8218+
RETVAL = &PL_sv_undef;
8219+
}
8220+
OUTPUT:
8221+
RETVAL

ext/XS-APItest/t/vstring.t

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!perl
2+
3+
use Test::More tests => 2;
4+
use XS::APItest;
5+
6+
{
7+
my $vstr = v1.23.456;
8+
ok SvVOK($vstr), '$vstr has SvVOK';
9+
is SvVSTRING($vstr), "v1.23.456", 'SvVSTRING()';
10+
}

proto.h

Lines changed: 5 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: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4741,10 +4741,10 @@ Perl_sv_setsv_flags(pTHX_ SV *dsv, SV* ssv, const I32 flags)
47414741
}
47424742
SvFLAGS(dsv) |= sflags & (SVf_IOK|SVp_IOK|SVf_NOK|SVp_NOK|SVf_UTF8);
47434743
{
4744-
const MAGIC * const smg = SvVSTRING_mg(ssv);
4745-
if (smg) {
4746-
sv_magic(dsv, NULL, PERL_MAGIC_vstring,
4747-
smg->mg_ptr, smg->mg_len);
4744+
const char *vstr_pv;
4745+
STRLEN vstr_len;
4746+
if ((vstr_pv = SvVSTRING(ssv, vstr_len))) {
4747+
sv_magic(dsv, NULL, PERL_MAGIC_vstring, vstr_pv, vstr_len);
47484748
SvRMAGICAL_on(dsv);
47494749
}
47504750
}
@@ -17891,6 +17891,34 @@ Perl_sv_regex_global_pos_clear(pTHX_ SV *sv)
1789117891
mg->mg_len = -1;
1789217892
}
1789317893

17894+
/*
17895+
=for apidoc sv_vstring_get
17896+
17897+
If the given SV has vstring magic, stores the length of it into the variable
17898+
addressed by C<lenp>, and returns the string pointer. If not, returns
17899+
C<NULL>.
17900+
17901+
If a pointer is returned to the caller, it will point to memory owned by the
17902+
SV itself. The caller is not responsible for freeing it after this call,
17903+
though it will not remain valid for longer than the lifetime of the SV itself.
17904+
The caller should take a copy of it if it needs to be accessed after this
17905+
time.
17906+
17907+
=cut
17908+
*/
17909+
17910+
const char *
17911+
Perl_sv_vstring_get(pTHX_ SV * const sv, STRLEN *lenp)
17912+
{
17913+
PERL_ARGS_ASSERT_SV_VSTRING_GET;
17914+
17915+
MAGIC *mg = SvVSTRING_mg(sv);
17916+
if(!mg) return NULL;
17917+
17918+
if(lenp) *lenp = mg->mg_len;
17919+
return mg->mg_ptr;
17920+
}
17921+
1789417922
/*
1789517923
* ex: set ts=8 sts=4 sw=4 et:
1789617924
*/

sv.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2843,6 +2843,21 @@ Create a new IO, setting the reference count to 1.
28432843
# define gv_dup_inc(s,t) MUTABLE_GV(sv_dup_inc((const SV *)s,t))
28442844
#endif
28452845

2846+
/*
2847+
=for apidoc Am|const char *|SvVSTRING |SV* sv|STRLEN len
2848+
2849+
If the given SV has vstring magic, stores the length of it into the variable
2850+
C<len>, and returns the string pointer. If not, returns C<NULL>.
2851+
2852+
This is a wrapper around the C<sv_vstring_get> function that conveniently
2853+
takes the address of the C<len> variable, in a form similar to the C<SvPV>
2854+
macro family.
2855+
2856+
=cut
2857+
*/
2858+
2859+
#define SvVSTRING(sv, len) (sv_vstring_get(sv, &(len)))
2860+
28462861
/*
28472862
* ex: set ts=8 sts=4 sw=4 et:
28482863
*/

0 commit comments

Comments
 (0)