Skip to content

Commit a2ecfe1

Browse files
committed
Added sv_regex_global_pos_get(), _set() and _clear()
These new API functions allow XS modules to interact with the stored `pos()` position without actually depending on the current magic-based implementation. This allows the internal mechanism to be altered in a future version without breaking such modules that use the abstraction API.
1 parent 0f78e38 commit a2ecfe1

File tree

12 files changed

+230
-44
lines changed

12 files changed

+230
-44
lines changed

MANIFEST

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5169,6 +5169,7 @@ ext/XS-APItest/t/printf.t XS::APItest extension
51695169
ext/XS-APItest/t/ptr_table.t Test ptr_table_* APIs
51705170
ext/XS-APItest/t/push.t XS::APItest extension
51715171
ext/XS-APItest/t/refs.t Test typemap ref handling
5172+
ext/XS-APItest/t/regex_global_pos.t Test regex_global_pos functions
51725173
ext/XS-APItest/t/rmagical.t XS::APItest extension
51735174
ext/XS-APItest/t/rpp_invoke_xs.t XS::APItest: test rpp_invoke_xs()
51745175
ext/XS-APItest/t/rv2cv_op_cv.t test rv2cv_op_cv() API

embed.fnc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3388,6 +3388,17 @@ AMTdip |void |SvREFCNT_inc_void \
33883388
|NULLOK SV *sv
33893389
ARdp |const char *|sv_reftype|NN const SV * const sv \
33903390
|const int ob
3391+
3392+
Adp |void |sv_regex_global_pos_clear \
3393+
|NN SV *sv
3394+
ARdp |bool |sv_regex_global_pos_get \
3395+
|NN SV *sv \
3396+
|NN STRLEN *posp \
3397+
|U32 flags
3398+
Adp |void |sv_regex_global_pos_set \
3399+
|NN SV *sv \
3400+
|STRLEN pos \
3401+
|U32 flags
33913402
Adp |void |sv_replace |NN SV * const sv \
33923403
|NN SV * const nsv
33933404
Adp |void |sv_report_used

embed.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,9 @@
780780
# define sv_recode_to_utf8(a,b) Perl_sv_recode_to_utf8(aTHX_ a,b)
781781
# define sv_ref(a,b,c) Perl_sv_ref(aTHX_ a,b,c)
782782
# define sv_reftype(a,b) Perl_sv_reftype(aTHX_ a,b)
783+
# define sv_regex_global_pos_clear(a) Perl_sv_regex_global_pos_clear(aTHX_ a)
784+
# define sv_regex_global_pos_get(a,b,c) Perl_sv_regex_global_pos_get(aTHX_ a,b,c)
785+
# define sv_regex_global_pos_set(a,b,c) Perl_sv_regex_global_pos_set(aTHX_ a,b,c)
783786
# define sv_replace(a,b) Perl_sv_replace(aTHX_ a,b)
784787
# define sv_report_used() Perl_sv_report_used(aTHX)
785788
# define sv_reset(a,b) Perl_sv_reset(aTHX_ a,b)

ext/XS-APItest/APItest.pm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use strict;
44
use warnings;
55
use Carp;
66

7-
our $VERSION = '1.40';
7+
our $VERSION = '1.41';
88

99
require XSLoader;
1010

ext/XS-APItest/APItest.xs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4959,6 +4959,20 @@ modify_pv(IV pi, IV sz)
49594959
/* used by op/pack.t when testing pack "p" */
49604960
memset(INT2PTR(char *, pi), 'y', sz);
49614961

4962+
STRLEN
4963+
sv_regex_global_pos_get(SV *sv, U32 flags = 0)
4964+
CODE:
4965+
if(!sv_regex_global_pos_get(sv, &RETVAL, flags))
4966+
XSRETURN_UNDEF;
4967+
OUTPUT:
4968+
RETVAL
4969+
4970+
void
4971+
sv_regex_global_pos_set(SV *sv, STRLEN pos, U32 flags = 0)
4972+
4973+
void
4974+
sv_regex_global_pos_clear(SV *sv)
4975+
49624976
MODULE = XS::APItest PACKAGE = XS::APItest::AUTOLOADtest
49634977

49644978
int

ext/XS-APItest/Makefile.PL

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ my @names = (qw(HV_DELETE HV_DISABLE_UVAR_XKEY HV_FETCH_ISSTORE
2525
G_SCALAR G_LIST G_VOID G_DISCARD G_EVAL G_NOARGS
2626
G_KEEPERR G_NODEBUG G_METHOD G_FAKINGEVAL G_RETHROW
2727
GV_NOADD_NOINIT G_USEHINTS
28-
SV_GMAGIC SV_SKIP_OVERLOAD
28+
SV_GMAGIC SV_SKIP_OVERLOAD SV_POSBYTES
2929
IS_NUMBER_IN_UV IS_NUMBER_GREATER_THAN_UV_MAX
3030
IS_NUMBER_NOT_INT IS_NUMBER_NEG IS_NUMBER_INFINITY
3131
IS_NUMBER_NAN IS_NUMBER_TRAILING PERL_SCAN_TRAILING

ext/XS-APItest/t/regex_global_pos.t

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#!perl
2+
3+
use v5.40;
4+
5+
use Test::More;
6+
7+
use XS::APItest;
8+
9+
# get
10+
{
11+
my $sv = "hello";
12+
is(sv_regex_global_pos_get($sv), undef, 'pos_get before setting');
13+
14+
$sv =~ m/.../gc;
15+
is(sv_regex_global_pos_get($sv), 3, 'pos_get after successful match');
16+
}
17+
18+
# set
19+
{
20+
my $sv = "hello";
21+
sv_regex_global_pos_set($sv, 2);
22+
is(pos($sv), 2, 'pos() after pos_set');
23+
24+
$sv =~ m/(.)/gc;
25+
is($1, "l", 'regexp match after pos_set');
26+
is(pos($sv), 3, 'pos() updated after match');
27+
28+
sv_regex_global_pos_set($sv, -1);
29+
is(pos($sv), 4, 'pos() after pos_set to -1');
30+
$sv =~ m/(.)/gc;
31+
is($1, "o", 'regexp match after pos_set to -1');
32+
33+
sv_regex_global_pos_clear($sv);
34+
$sv =~ m/(.)/gc;
35+
is($1, "h", 'regexp match after pos clear');
36+
}
37+
38+
# characters vs bytes
39+
{
40+
use utf8;
41+
my $sv = "café here";
42+
43+
# pos should be 5 characters even though it is 6 bytes
44+
$sv =~ m/ /gc;
45+
is(sv_regex_global_pos_get($sv), 5, 'pos_get returns count in chars');
46+
# can query position in bytes directly
47+
is(sv_regex_global_pos_get($sv, SV_POSBYTES), 6, 'pos_get with SV_POSBYTES returns count in bytes');
48+
49+
pos($sv) = 0;
50+
sv_regex_global_pos_set($sv, 4);
51+
$sv =~ m/(.)/gc;
52+
is($1, " ", 'regexp match after pos_set in chars');
53+
54+
pos($sv) = 0;
55+
sv_regex_global_pos_set($sv, 5, SV_POSBYTES);
56+
$sv =~ m/(.)/gc;
57+
is($1, " ", 'regexp match after pos_set in bytes');
58+
}
59+
60+
done_testing;

mg.c

Lines changed: 8 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2439,17 +2439,14 @@ int
24392439
Perl_magic_getpos(pTHX_ SV *sv, MAGIC *mg)
24402440
{
24412441
SV* const lsv = LvTARG(sv);
2442-
MAGIC * const found = mg_find_mglob(lsv);
24432442

24442443
PERL_ARGS_ASSERT_MAGIC_GETPOS;
24452444
PERL_UNUSED_ARG(mg);
24462445

2447-
if (found && found->mg_len != -1) {
2448-
STRLEN i = found->mg_len;
2449-
if (found->mg_flags & MGf_BYTES && DO_UTF8(lsv))
2450-
i = sv_pos_b2u_flags(lsv, i, SV_GMAGIC|SV_CONST_RETURN);
2451-
sv_setuv(sv, i);
2452-
return 0;
2446+
STRLEN pos;
2447+
if (sv_regex_global_pos_get(lsv, &pos, 0)) {
2448+
sv_setuv(sv, pos);
2449+
return 0;
24532450
}
24542451
sv_set_undef(sv);
24552452
return 0;
@@ -2459,44 +2456,14 @@ int
24592456
Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg)
24602457
{
24612458
SV* const lsv = LvTARG(sv);
2462-
SSize_t pos;
2463-
STRLEN len;
2464-
MAGIC* found;
2465-
const char *s;
24662459

24672460
PERL_ARGS_ASSERT_MAGIC_SETPOS;
24682461
PERL_UNUSED_ARG(mg);
24692462

2470-
found = mg_find_mglob(lsv);
2471-
if (!found) {
2472-
if (!SvOK(sv))
2473-
return 0;
2474-
found = sv_magicext_mglob(lsv);
2475-
}
2476-
else if (!SvOK(sv)) {
2477-
found->mg_len = -1;
2478-
return 0;
2479-
}
2480-
s = SvPV_const(lsv, len);
2481-
2482-
pos = SvIV(sv);
2483-
2484-
if (DO_UTF8(lsv)) {
2485-
const STRLEN ulen = sv_or_pv_len_utf8(lsv, s, len);
2486-
if (ulen)
2487-
len = ulen;
2488-
}
2489-
2490-
if (pos < 0) {
2491-
pos += len;
2492-
if (pos < 0)
2493-
pos = 0;
2494-
}
2495-
else if (pos > (SSize_t)len)
2496-
pos = len;
2497-
2498-
found->mg_len = pos;
2499-
found->mg_flags &= ~(MGf_MINMATCH|MGf_BYTES);
2463+
if(SvOK(sv))
2464+
sv_regex_global_pos_set(lsv, SvIV(sv), 0);
2465+
else
2466+
sv_regex_global_pos_clear(lsv);
25002467

25012468
return 0;
25022469
}

pod/perldelta.pod

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,12 @@ well.
348348

349349
=item *
350350

351-
XXX
351+
Three new API functions have been added to interact with the regexp global
352+
match position stored in an SV. These are C<sv_regex_global_pos_get()>,
353+
C<sv_regex_global_pos_set()> and C<sv_regex_global_pos_clear()>. Using these
354+
API functions avoids XS modules needing to know about or interact directly
355+
with the way this position is currently stored, which involves the
356+
C<PERL_MAGIC_regex_global> magic type.
352357

353358
=back
354359

proto.h

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

0 commit comments

Comments
 (0)