diff options
author | NAITOH Jun <[email protected]> | 2025-02-23 10:21:16 +0900 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2025-02-25 15:36:46 +0900 |
commit | 36ab247e4d2fa7fa82142d9f70b340b28da05274 (patch) | |
tree | be451a2b6b07510b80be7ed7a560f9b867c4cf11 | |
parent | 021ccbf7e8e34a1ae7af2d8411ed6dc4e5e8f980 (diff) |
[ruby/strscan] Fix a bug that scanning methods that don't use Regexp
don't clear named capture groups
(https://github.com/ruby/strscan/pull/142)
Fix https://github.com/ruby/strscan/pull/135
https://github.com/ruby/strscan/commit/b957443e20
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/12804
-rw-r--r-- | ext/strscan/strscan.c | 10 | ||||
-rw-r--r-- | test/strscan/test_stringscanner.rb | 36 |
2 files changed, 36 insertions, 10 deletions
diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c index e5a0ad66a3..86a60280ca 100644 --- a/ext/strscan/strscan.c +++ b/ext/strscan/strscan.c @@ -58,8 +58,13 @@ struct strscanner }; #define MATCHED_P(s) ((s)->flags & FLAG_MATCHED) -#define MATCHED(s) (s)->flags |= FLAG_MATCHED -#define CLEAR_MATCH_STATUS(s) (s)->flags &= ~FLAG_MATCHED +#define MATCHED(s) ((s)->flags |= FLAG_MATCHED) +#define CLEAR_MATCHED(s) ((s)->flags &= ~FLAG_MATCHED) +#define CLEAR_NAMED_CAPTURES(s) ((s)->regex = Qnil) +#define CLEAR_MATCH_STATUS(s) do {\ + CLEAR_MATCHED(s);\ + CLEAR_NAMED_CAPTURES(s);\ +} while (0) #define S_PBEG(s) (RSTRING_PTR((s)->str)) #define S_LEN(s) (RSTRING_LEN((s)->str)) @@ -216,7 +221,6 @@ strscan_s_allocate(VALUE klass) CLEAR_MATCH_STATUS(p); onig_region_init(&(p->regs)); p->str = Qnil; - p->regex = Qnil; return obj; } diff --git a/test/strscan/test_stringscanner.rb b/test/strscan/test_stringscanner.rb index 2f68331da5..ece6ceef6f 100644 --- a/test/strscan/test_stringscanner.rb +++ b/test/strscan/test_stringscanner.rb @@ -22,7 +22,9 @@ module StringScannerTests def test_scan_byte omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby" s = create_string_scanner('ab') + assert_equal(2, s.match?(/(?<a>ab)/)) # set named_captures assert_equal(97, s.scan_byte) + assert_equal({}, s.named_captures) assert_equal(98, s.scan_byte) assert_nil(s.scan_byte) @@ -176,11 +178,13 @@ module StringScannerTests end def test_string + omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby" s = create_string_scanner('test string') assert_equal('test string', s.string) - s.scan(/test/) + s.scan(/(?<t>test)/) # set named_captures assert_equal('test string', s.string) s.string = 'a' + assert_equal({}, s.named_captures) assert_equal('a', s.string) s.scan(/a/) s.string = 'b' @@ -366,8 +370,11 @@ module StringScannerTests end def test_getch + omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby" s = create_string_scanner('abcde') + assert_equal(3, s.match?(/(?<a>abc)/)) # set named_captures assert_equal('a', s.getch) + assert_equal({}, s.named_captures) assert_equal('b', s.getch) assert_equal('c', s.getch) assert_equal('d', s.getch) @@ -385,8 +392,11 @@ module StringScannerTests end def test_get_byte + omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby" s = create_string_scanner('abcde') + assert_equal(3, s.match?(/(?<a>abc)/)) # set named_captures assert_equal('a', s.get_byte) + assert_equal({}, s.named_captures) assert_equal('b', s.get_byte) assert_equal('c', s.get_byte) assert_equal('d', s.get_byte) @@ -602,18 +612,22 @@ module StringScannerTests end def test_terminate - s = create_string_scanner('ssss') - s.getch + omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby" + s = create_string_scanner('abcd') + s.scan(/(?<a>ab)/) # set named_captures s.terminate + assert_equal({}, s.named_captures) assert_equal(true, s.eos?) s.terminate assert_equal(true, s.eos?) end def test_reset - s = create_string_scanner('ssss') - s.getch + omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby" + s = create_string_scanner('abcd') + s.scan(/(?<a>ab)/) # set named_captures s.reset + assert_equal({}, s.named_captures) assert_equal(0, s.pos) s.scan(/\w+/) s.reset @@ -848,9 +862,11 @@ module StringScannerTests end def test_unscan + omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby" s = create_string_scanner('test string') - assert_equal("test", s.scan(/\w+/)) + assert_equal(4, s.skip(/(?<t>test)/)) # set named_captures s.unscan + assert_equal({}, s.named_captures) assert_equal("te", s.scan(/../)) assert_equal(nil, s.scan(/\d/)) assert_raise(ScanError) { s.unscan } @@ -939,18 +955,22 @@ module StringScannerTests end def test_named_captures - omit("not implemented on TruffleRuby") if ["truffleruby"].include?(RUBY_ENGINE) + omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby" scan = StringScanner.new("foobarbaz") assert_equal({}, scan.named_captures) assert_equal(9, scan.match?(/(?<f>foo)(?<r>bar)(?<z>baz)/)) assert_equal({"f" => "foo", "r" => "bar", "z" => "baz"}, scan.named_captures) + assert_equal(9, scan.match?("foobarbaz")) + assert_equal({}, scan.named_captures) end def test_scan_integer omit("scan_integer isn't implemented on TruffleRuby yet") if RUBY_ENGINE == "truffleruby" s = create_string_scanner('abc') + assert_equal(3, s.match?(/(?<a>abc)/)) # set named_captures assert_nil(s.scan_integer) + assert_equal({}, s.named_captures) assert_equal(0, s.pos) refute_predicate(s, :matched?) @@ -1022,7 +1042,9 @@ module StringScannerTests assert_predicate(s, :matched?) s = create_string_scanner('abc') + assert_equal(3, s.match?(/(?<a>abc)/)) # set named_captures assert_equal(0xabc, s.scan_integer(base: 16)) + assert_equal({}, s.named_captures) assert_equal(3, s.pos) assert_predicate(s, :matched?) |