Skip to content

Commit eee9bd1

Browse files
naitohhsbt
authored andcommitted
[ruby/strscan] Fix a bug that scan_until behaves differently with
Regexp and String patterns (ruby/strscan#138) Fix ruby/strscan#131 ruby/strscan@e1cec2e726
1 parent 6b3a97d commit eee9bd1

File tree

2 files changed

+68
-12
lines changed

2 files changed

+68
-12
lines changed

ext/strscan/strscan.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -571,19 +571,20 @@ match_target(struct strscanner *p)
571571
}
572572

573573
static inline void
574-
set_registers(struct strscanner *p, size_t length)
574+
set_registers(struct strscanner *p, size_t pos, size_t length)
575575
{
576576
const int at = 0;
577577
OnigRegion *regs = &(p->regs);
578578
onig_region_clear(regs);
579579
if (onig_region_set(regs, at, 0, 0)) return;
580580
if (p->fixed_anchor_p) {
581-
regs->beg[at] = p->curr;
582-
regs->end[at] = p->curr + length;
581+
regs->beg[at] = pos + p->curr;
582+
regs->end[at] = pos + p->curr + length;
583583
}
584584
else
585585
{
586-
regs->end[at] = length;
586+
regs->beg[at] = pos;
587+
regs->end[at] = pos + length;
587588
}
588589
}
589590

@@ -731,7 +732,7 @@ strscan_do_scan(VALUE self, VALUE pattern, int succptr, int getstr, int headonly
731732
if (memcmp(CURPTR(p), RSTRING_PTR(pattern), RSTRING_LEN(pattern)) != 0) {
732733
return Qnil;
733734
}
734-
set_registers(p, RSTRING_LEN(pattern));
735+
set_registers(p, 0, RSTRING_LEN(pattern));
735736
}
736737
else {
737738
rb_encoding *enc = rb_enc_check(p->str, pattern);
@@ -740,7 +741,7 @@ strscan_do_scan(VALUE self, VALUE pattern, int succptr, int getstr, int headonly
740741
if (pos == -1) {
741742
return Qnil;
742743
}
743-
set_registers(p, RSTRING_LEN(pattern) + pos);
744+
set_registers(p, pos, RSTRING_LEN(pattern));
744745
}
745746
}
746747

test/strscan/test_stringscanner.rb

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -409,12 +409,8 @@ def test_matched
409409
s = create_string_scanner('stra strb strc')
410410
s.scan(/\w+/)
411411
assert_equal('stra', s.matched)
412-
s.scan(/\s+/)
413-
assert_equal(' ', s.matched)
414-
s.scan('st')
415-
assert_equal('st', s.matched)
416-
s.scan(/\w+/)
417-
assert_equal('rb', s.matched)
412+
s.scan_until(/\w+/)
413+
assert_equal('strb', s.matched)
418414
s.scan(/\s+/)
419415
assert_equal(' ', s.matched)
420416
s.scan(/\w+/)
@@ -432,6 +428,23 @@ def test_matched
432428
assert_equal('t', s.matched)
433429
end
434430

431+
def test_matched_string
432+
omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby"
433+
s = create_string_scanner('stra strb strc')
434+
s.scan('stra')
435+
assert_equal('stra', s.matched)
436+
s.scan_until('strb')
437+
assert_equal('strb', s.matched)
438+
s.scan(' ')
439+
assert_equal(' ', s.matched)
440+
s.scan('strc')
441+
assert_equal('strc', s.matched)
442+
s.scan('c')
443+
assert_nil(s.matched)
444+
s.getch
445+
assert_nil(s.matched)
446+
end
447+
435448
def test_AREF
436449
s = create_string_scanner('stra strb strc')
437450

@@ -522,6 +535,27 @@ def test_pre_match
522535
assert_nil(s.pre_match)
523536
end
524537

538+
def test_pre_match_string
539+
omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby"
540+
s = create_string_scanner('a b c d e')
541+
s.scan('a')
542+
assert_equal('', s.pre_match)
543+
s.skip(' ')
544+
assert_equal('a', s.pre_match)
545+
s.scan('b')
546+
assert_equal('a ', s.pre_match)
547+
s.scan_until('c')
548+
assert_equal('a b ', s.pre_match)
549+
s.getch
550+
assert_equal('a b c', s.pre_match)
551+
s.get_byte
552+
assert_equal('a b c ', s.pre_match)
553+
s.get_byte
554+
assert_equal('a b c d', s.pre_match)
555+
s.scan('never match')
556+
assert_nil(s.pre_match)
557+
end
558+
525559
def test_post_match
526560
s = create_string_scanner('a b c d e')
527561
s.scan(/\w/)
@@ -546,6 +580,27 @@ def test_post_match
546580
assert_nil(s.post_match)
547581
end
548582

583+
def test_post_match_string
584+
omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby"
585+
s = create_string_scanner('a b c d e')
586+
s.scan('a')
587+
assert_equal(' b c d e', s.post_match)
588+
s.skip(' ')
589+
assert_equal('b c d e', s.post_match)
590+
s.scan('b')
591+
assert_equal(' c d e', s.post_match)
592+
s.scan_until('c')
593+
assert_equal(' d e', s.post_match)
594+
s.getch
595+
assert_equal('d e', s.post_match)
596+
s.get_byte
597+
assert_equal(' e', s.post_match)
598+
s.get_byte
599+
assert_equal('e', s.post_match)
600+
s.scan('never match')
601+
assert_nil(s.post_match)
602+
end
603+
549604
def test_terminate
550605
s = create_string_scanner('ssss')
551606
s.getch

0 commit comments

Comments
 (0)