@@ -1574,7 +1574,7 @@ public:
1574
1574
};
1575
1575
1576
1576
struct _Loop_vals_v2_t { // storage for loop administration
1577
- void* _Loop_iter = nullptr ;
1577
+ size_t _Loop_frame_idx = 0 ;
1578
1578
int _Loop_idx = 0;
1579
1579
unsigned int _Group_first = 0;
1580
1580
};
@@ -1736,10 +1736,14 @@ public:
1736
1736
_Full = _Full_match;
1737
1737
_Max_complexity_count = _REGEX_MAX_COMPLEXITY_COUNT;
1738
1738
_Max_stack_count = _REGEX_MAX_STACK_COUNT;
1739
+ _Frames_count = 0;
1739
1740
1740
1741
_Matched = false;
1741
1742
1742
- if (!_Match_pat(_Rep)) {
1743
+ bool _Succeeded = _Match_pat(_Rep);
1744
+ _STL_INTERNAL_CHECK(_Frames_count == 0);
1745
+
1746
+ if (!_Succeeded) {
1743
1747
return false;
1744
1748
}
1745
1749
@@ -1784,6 +1788,11 @@ private:
1784
1788
_Tgt_state_t<_It> _Tgt_state;
1785
1789
_Tgt_state_t<_It> _Res;
1786
1790
vector<_Loop_vals_v2_t> _Loop_vals;
1791
+ vector<_Tgt_state_t<_It>> _Frames;
1792
+ size_t _Frames_count;
1793
+
1794
+ size_t _Push_frame();
1795
+ void _Pop_frame(size_t);
1787
1796
1788
1797
bool _Do_assert(_Node_assert*);
1789
1798
bool _Do_neg_assert(_Node_assert*);
@@ -3338,6 +3347,22 @@ void _Builder2<_FwdIt, _Elem, _RxTraits>::_Tidy() noexcept { // free memory
3338
3347
_Root = nullptr;
3339
3348
}
3340
3349
3350
+ template <class _BidIt, class _Elem, class _RxTraits, class _It, class _Alloc>
3351
+ size_t _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Push_frame() {
3352
+ if (_Frames_count >= _Frames.size()) {
3353
+ _Frames.push_back(_Tgt_state);
3354
+ } else {
3355
+ _Frames[_Frames_count] = _Tgt_state;
3356
+ }
3357
+ return _Frames_count++;
3358
+ }
3359
+
3360
+ template <class _BidIt, class _Elem, class _RxTraits, class _It, class _Alloc>
3361
+ void _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Pop_frame(size_t _Idx) {
3362
+ _STL_INTERNAL_CHECK(_Idx + 1 == _Frames_count);
3363
+ _Frames_count = _Idx;
3364
+ }
3365
+
3341
3366
template <class _BidIt, class _Elem, class _RxTraits, class _It, class _Alloc>
3342
3367
bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_assert(_Node_assert* _Node) { // apply assert node
3343
3368
_It _Ch = _Tgt_state._Cur;
@@ -3352,34 +3377,37 @@ bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_assert(_Node_assert*
3352
3377
template <class _BidIt, class _Elem, class _RxTraits, class _It, class _Alloc>
3353
3378
bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_neg_assert(_Node_assert* _Node) {
3354
3379
// apply negative assert node
3355
- _Bt_state_t<_It> _St = _Tgt_state;
3356
- if (!_Match_pat(_Node->_Child)) {
3357
- _Tgt_state = _St;
3358
- return true;
3359
- } else {
3360
- return false;
3380
+ const size_t _Frame_idx = _Push_frame();
3381
+ bool _Succeeded = !_Match_pat(_Node->_Child);
3382
+ if (_Succeeded) {
3383
+ const _Bt_state_t<_It>& _St = _Frames[_Frame_idx];
3384
+ _Tgt_state = _St;
3361
3385
}
3386
+ _Pop_frame(_Frame_idx);
3387
+ return _Succeeded;
3362
3388
}
3363
3389
3364
3390
template <class _BidIt, class _Elem, class _RxTraits, class _It, class _Alloc>
3365
3391
bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_if(_Node_if* _Node) { // apply if node
3366
- _Tgt_state_t<_It> _St = _Tgt_state ;
3392
+ const size_t _Frame_idx = _Push_frame() ;
3367
3393
3368
3394
// look for the first match
3369
3395
for (; _Node; _Node = _Node->_Child) { // process one branch of if
3370
- _Tgt_state = _St ; // rewind to where the alternation starts in input
3396
+ _Tgt_state = _Frames[_Frame_idx] ; // rewind to where the alternation starts in input
3371
3397
if (_Match_pat(_Node->_Next)) { // try to match this branch
3372
3398
break;
3373
3399
}
3374
3400
}
3375
3401
3376
3402
// if none of the if branches matched, fail to match
3377
3403
if (!_Node) {
3404
+ _Pop_frame(_Frame_idx);
3378
3405
return false;
3379
3406
}
3380
3407
3381
3408
// if we aren't looking for the longest match, that's it
3382
3409
if (!_Longest) {
3410
+ _Pop_frame(_Frame_idx);
3383
3411
return true;
3384
3412
}
3385
3413
@@ -3390,32 +3418,36 @@ bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_if(_Node_if* _Node) {
3390
3418
break;
3391
3419
}
3392
3420
3393
- _Tgt_state = _St ;
3421
+ _Tgt_state = _Frames[_Frame_idx] ;
3394
3422
(void) _Match_pat(_Node->_Next);
3395
3423
}
3424
+ _Pop_frame(_Frame_idx);
3396
3425
return true;
3397
3426
}
3398
3427
3399
3428
template <class _BidIt, class _Elem, class _RxTraits, class _It, class _Alloc>
3400
3429
bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_rep0(_Node_rep* _Node, bool _Greedy) {
3401
3430
// apply repetition to loop with no nested if/do
3402
- int _Ix = 0;
3403
- _Tgt_state_t<_It> _St = _Tgt_state ;
3431
+ int _Ix = 0;
3432
+ const size_t _Frame_idx = _Push_frame() ;
3404
3433
3405
3434
if (0 < _Node->_Min) {
3406
3435
// GH-5365: We can avoid resetting capture groups for the first iteration
3407
3436
// because we know that a simple repetition of this loop was not encountered before.
3408
3437
if (!_Match_pat(_Node->_Next)) { // didn't match minimum number of reps, fail
3438
+ _Pop_frame(_Frame_idx);
3409
3439
return false;
3410
- } else if (_Tgt_state._Cur == _St ._Cur) { // matches empty string
3440
+ } else if (_Tgt_state._Cur == _Frames[_Frame_idx] ._Cur) { // matches empty string
3411
3441
// loop is branchless, so it will only ever match empty strings
3412
3442
// -> skip all other matches as they don't change state and immediately try tail
3443
+ _Pop_frame(_Frame_idx);
3413
3444
return _Match_pat(_Node->_End_rep->_Next);
3414
3445
} else { // loop never matches the empty string
3415
3446
for (_Ix = 1; _Ix < _Node->_Min; ++_Ix) { // do minimum number of reps
3416
3447
// GH-5365: We have to reset the capture groups from the second iteration on.
3417
- _Tgt_state._Grp_valid = _St ._Grp_valid;
3448
+ _Tgt_state._Grp_valid = _Frames[_Frame_idx] ._Grp_valid;
3418
3449
if (!_Match_pat(_Node->_Next)) { // didn't match minimum number of reps, fail
3450
+ _Pop_frame(_Frame_idx);
3419
3451
return false;
3420
3452
}
3421
3453
}
@@ -3429,6 +3461,7 @@ bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_rep0(_Node_rep* _Node
3429
3461
3430
3462
if (_Match_pat(_Node->_End_rep->_Next)) {
3431
3463
if (!_Greedy) {
3464
+ _Pop_frame(_Frame_idx);
3432
3465
return true; // go with current match
3433
3466
}
3434
3467
@@ -3439,20 +3472,22 @@ bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_rep0(_Node_rep* _Node
3439
3472
3440
3473
if (_Ix == 0 && _Node->_Max != 0) {
3441
3474
_Tgt_state._Cur = _Saved_pos;
3442
- _Tgt_state._Grp_valid = _St ._Grp_valid;
3475
+ _Tgt_state._Grp_valid = _Frames[_Frame_idx] ._Grp_valid;
3443
3476
3444
3477
if (!_Match_pat(_Node->_Next)) { // rep match failed, we are done
3445
3478
_Done = true;
3446
3479
} else if (_Saved_pos == _Tgt_state._Cur) { // match empty, try no more repetitions
3447
3480
_Done = true;
3448
3481
// we only potentially accept/try tail for POSIX
3449
3482
if ((_Sflags & regex_constants::_Any_posix) && _Match_pat(_Node->_End_rep->_Next)) {
3483
+ _Pop_frame(_Frame_idx);
3450
3484
return true; // go with current match
3451
3485
}
3452
3486
} else {
3453
3487
_Saved_pos = _Tgt_state._Cur;
3454
3488
if (_Match_pat(_Node->_End_rep->_Next)) {
3455
3489
if (!_Greedy) {
3490
+ _Pop_frame(_Frame_idx);
3456
3491
return true; // go with current match
3457
3492
}
3458
3493
@@ -3467,7 +3502,7 @@ bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_rep0(_Node_rep* _Node
3467
3502
if (!_Done) {
3468
3503
while (_Node->_Max == -1 || _Ix++ < _Node->_Max) { // try another rep/tail match
3469
3504
_Tgt_state._Cur = _Saved_pos;
3470
- _Tgt_state._Grp_valid = _St ._Grp_valid;
3505
+ _Tgt_state._Grp_valid = _Frames[_Frame_idx] ._Grp_valid;
3471
3506
if (!_Match_pat(_Node->_Next) || _Tgt_state._Cur == _Saved_pos) {
3472
3507
break; // rep match failed, quit loop
3473
3508
}
@@ -3476,6 +3511,7 @@ bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_rep0(_Node_rep* _Node
3476
3511
_Saved_pos = _Tgt_state._Cur;
3477
3512
if (_Match_pat(_Node->_End_rep->_Next)) {
3478
3513
if (!_Greedy) {
3514
+ _Pop_frame(_Frame_idx);
3479
3515
return true; // go with current match
3480
3516
}
3481
3517
@@ -3489,22 +3525,24 @@ bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_rep0(_Node_rep* _Node
3489
3525
if (_Matched0) { // record final match
3490
3526
_Tgt_state = _Final;
3491
3527
}
3528
+
3529
+ _Pop_frame(_Frame_idx);
3492
3530
return _Matched0;
3493
3531
}
3494
3532
3495
3533
template <class _BidIt, class _Elem, class _RxTraits, class _It, class _Alloc>
3496
3534
bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_rep(_Node_rep* _Node, bool _Greedy, int _Init_idx) {
3497
3535
// apply repetition
3498
- bool _Matched0 = false;
3499
- _Tgt_state_t<_It> _St = _Tgt_state ;
3500
- _Loop_vals_v2_t* _Psav = &_Loop_vals[_Node->_Loop_number] ;
3501
- int _Loop_idx_sav = _Psav->_Loop_idx ;
3502
- _It* _Loop_iter_sav = static_cast<_It*>(_Psav->_Loop_iter );
3503
- bool _Progress = _Init_idx == 0 || *_Loop_iter_sav != _St ._Cur;
3536
+ bool _Matched0 = false;
3537
+ _Loop_vals_v2_t* _Psav = &_Loop_vals[_Node->_Loop_number] ;
3538
+ const int _Loop_idx_sav = _Psav->_Loop_idx ;
3539
+ const size_t _Loop_frame_idx_sav = _Psav->_Loop_frame_idx ;
3540
+ const size_t _Frame_idx = _Push_frame( );
3541
+ const bool _Progress = _Init_idx == 0 || _Frames[_Loop_frame_idx_sav]._Cur != _Tgt_state ._Cur;
3504
3542
3505
3543
if (_Init_idx < _Node->_Min) { // try another required match
3506
- _Psav->_Loop_iter = _STD addressof(_St._Cur) ;
3507
- _Psav->_Loop_idx = _Progress ? _Init_idx + 1 : _Node->_Min; // try only one more match after an empty match
3544
+ _Psav->_Loop_frame_idx = _Frame_idx ;
3545
+ _Psav->_Loop_idx = _Progress ? _Init_idx + 1 : _Node->_Min; // try only one more match after an empty match
3508
3546
_STD fill(_Tgt_state._Grp_valid.begin() + static_cast<ptrdiff_t>(_Psav->_Group_first),
3509
3547
_Tgt_state._Grp_valid.end(), false);
3510
3548
_Matched0 = _Match_pat(_Node->_Next);
@@ -3517,35 +3555,35 @@ bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_rep(_Node_rep* _Node,
3517
3555
_Matched0 = _Match_pat(_Node->_End_rep->_Next);
3518
3556
3519
3557
// try to match with one more repetition
3520
- _Tgt_state = _St ;
3521
- _Psav->_Loop_idx = _Init_idx + 1;
3522
- _Psav->_Loop_iter = _STD addressof(_St._Cur) ;
3558
+ _Tgt_state = _Frames[_Frame_idx] ;
3559
+ _Psav->_Loop_idx = _Init_idx + 1;
3560
+ _Psav->_Loop_frame_idx = _Frame_idx ;
3523
3561
if (_Match_pat(_Node->_Next)) { // always call _Match_pat, even when _Matched0 is already true
3524
3562
_Matched0 = true;
3525
3563
}
3526
3564
} else if (!_Greedy) { // not greedy, favor minimum number of reps
3527
3565
_Matched0 = _Match_pat(_Node->_End_rep->_Next);
3528
3566
if (!_Matched0) { // tail failed, try another rep
3529
- _Tgt_state = _St ;
3530
- _Psav->_Loop_idx = _Init_idx + 1;
3531
- _Psav->_Loop_iter = _STD addressof(_St._Cur) ;
3567
+ _Tgt_state = _Frames[_Frame_idx] ;
3568
+ _Psav->_Loop_idx = _Init_idx + 1;
3569
+ _Psav->_Loop_frame_idx = _Frame_idx ;
3532
3570
_STD fill(_Tgt_state._Grp_valid.begin() + static_cast<ptrdiff_t>(_Psav->_Group_first),
3533
3571
_Tgt_state._Grp_valid.end(), false);
3534
3572
_Matched0 = _Match_pat(_Node->_Next);
3535
3573
}
3536
3574
} else { // greedy, favor maximum number of reps,
3537
3575
// so try another rep
3538
- _Psav->_Loop_idx = _Init_idx + 1;
3539
- _Psav->_Loop_iter = _STD addressof(_St._Cur) ;
3576
+ _Psav->_Loop_idx = _Init_idx + 1;
3577
+ _Psav->_Loop_frame_idx = _Frame_idx ;
3540
3578
_STD fill(_Tgt_state._Grp_valid.begin() + static_cast<ptrdiff_t>(_Psav->_Group_first),
3541
3579
_Tgt_state._Grp_valid.end(), false);
3542
3580
_Matched0 = _Match_pat(_Node->_Next);
3543
3581
3544
3582
if (!_Matched0) { // rep failed, try tail
3545
- _Psav->_Loop_idx = _Loop_idx_sav;
3546
- _Psav->_Loop_iter = _Loop_iter_sav ;
3547
- _Tgt_state = _St ;
3548
- _Matched0 = _Match_pat(_Node->_End_rep->_Next);
3583
+ _Psav->_Loop_idx = _Loop_idx_sav;
3584
+ _Psav->_Loop_frame_idx = _Loop_frame_idx_sav ;
3585
+ _Tgt_state = _Frames[_Frame_idx] ;
3586
+ _Matched0 = _Match_pat(_Node->_End_rep->_Next);
3549
3587
}
3550
3588
}
3551
3589
} else if (_Init_idx == 1 && (_Sflags & regex_constants::_Any_posix)) {
@@ -3554,8 +3592,9 @@ bool _Matcher2<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_rep(_Node_rep* _Node,
3554
3592
_Matched0 = _Match_pat(_Node->_End_rep->_Next);
3555
3593
}
3556
3594
3557
- _Psav->_Loop_idx = _Loop_idx_sav;
3558
- _Psav->_Loop_iter = _Loop_iter_sav;
3595
+ _Psav->_Loop_idx = _Loop_idx_sav;
3596
+ _Psav->_Loop_frame_idx = _Loop_frame_idx_sav;
3597
+ _Pop_frame(_Frame_idx);
3559
3598
return _Matched0;
3560
3599
}
3561
3600
0 commit comments