diff options
author | Hiroshi SHIBATA <[email protected]> | 2022-12-09 13:03:33 +0900 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2022-12-09 16:36:22 +0900 |
commit | 4e31fea77d360c6535e33ff2525d80fba38d15d8 (patch) | |
tree | 92bdeec2cadb323f10197d1013c699589feb83d0 | |
parent | bcf01b18cfe9b21bfde32e28edd4745703bf190c (diff) |
Merge strscan-3.0.5
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/6890
-rw-r--r-- | ext/strscan/extconf.rb | 10 | ||||
-rw-r--r-- | ext/strscan/strscan.c | 64 | ||||
-rw-r--r-- | ext/strscan/strscan.gemspec | 23 | ||||
-rw-r--r-- | test/strscan/test_ractor.rb | 2 | ||||
-rw-r--r-- | test/strscan/test_stringscanner.rb | 33 |
5 files changed, 117 insertions, 15 deletions
diff --git a/ext/strscan/extconf.rb b/ext/strscan/extconf.rb index f0ecbf85d8..b53b63e455 100644 --- a/ext/strscan/extconf.rb +++ b/ext/strscan/extconf.rb @@ -1,5 +1,9 @@ # frozen_string_literal: true require 'mkmf' -$INCFLAGS << " -I$(top_srcdir)" if $extmk -have_func("onig_region_memsize", "ruby.h") -create_makefile 'strscan' +if RUBY_ENGINE == 'ruby' + $INCFLAGS << " -I$(top_srcdir)" if $extmk + have_func("onig_region_memsize", "ruby.h") + create_makefile 'strscan' +else + File.write('Makefile', dummy_makefile("").join) +end diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c index e1426380b4..9b646ab678 100644 --- a/ext/strscan/strscan.c +++ b/ext/strscan/strscan.c @@ -22,7 +22,7 @@ extern size_t onig_region_memsize(const struct re_registers *regs); #include <stdbool.h> -#define STRSCAN_VERSION "3.0.1" +#define STRSCAN_VERSION "3.0.5" /* ======================================================================= Data Type Definitions @@ -435,11 +435,11 @@ strscan_get_pos(VALUE self) * * In short, it's a 0-based index into the string. * - * s = StringScanner.new("abcädeföghi") - * s.charpos # -> 0 - * s.scan_until(/ä/) # -> "abcä" - * s.pos # -> 5 - * s.charpos # -> 4 + * s = StringScanner.new("abc\u00e4def\u00f6ghi") + * s.charpos # -> 0 + * s.scan_until(/\u00e4/) # -> "abc\u00E4" + * s.pos # -> 5 + * s.charpos # -> 4 */ static VALUE strscan_get_charpos(VALUE self) @@ -1458,6 +1458,54 @@ strscan_fixed_anchor_p(VALUE self) return p->fixed_anchor_p ? Qtrue : Qfalse; } +typedef struct { + VALUE self; + VALUE captures; +} named_captures_data; + +static int +named_captures_iter(const OnigUChar *name, + const OnigUChar *name_end, + int back_num, + int *back_refs, + OnigRegex regex, + void *arg) +{ + named_captures_data *data = arg; + + VALUE key = rb_str_new((const char *)name, name_end - name); + VALUE value = RUBY_Qnil; + int i; + for (i = 0; i < back_num; i++) { + value = strscan_aref(data->self, INT2NUM(back_refs[i])); + } + rb_hash_aset(data->captures, key, value); + return 0; +} + +/* + * call-seq: + * scanner.named_captures -> hash + * + * Returns a hash of string variables matching the regular expression. + * + * scan = StringScanner.new('foobarbaz') + * scan.match?(/(?<f>foo)(?<r>bar)(?<z>baz)/) + * scan.named_captures # -> {"f"=>"foo", "r"=>"bar", "z"=>"baz"} + */ +static VALUE +strscan_named_captures(VALUE self) +{ + struct strscanner *p; + GET_SCANNER(self, p); + named_captures_data data; + data.self = self; + data.captures = rb_hash_new(); + onig_foreach_name(RREGEXP_PTR(p->regex), named_captures_iter, &data); + + return data.captures; +} + /* ======================================================================= Ruby Interface ======================================================================= */ @@ -1468,6 +1516,8 @@ strscan_fixed_anchor_p(VALUE self) * StringScanner provides for lexical scanning operations on a String. Here is * an example of its usage: * + * require 'strscan' + * * s = StringScanner.new('This is an example string') * s.eos? # -> false * @@ -1650,4 +1700,6 @@ Init_strscan(void) rb_define_method(StringScanner, "inspect", strscan_inspect, 0); rb_define_method(StringScanner, "fixed_anchor?", strscan_fixed_anchor_p, 0); + + rb_define_method(StringScanner, "named_captures", strscan_named_captures, 0); } diff --git a/ext/strscan/strscan.gemspec b/ext/strscan/strscan.gemspec index 5d8119ea4c..8a61c7abe6 100644 --- a/ext/strscan/strscan.gemspec +++ b/ext/strscan/strscan.gemspec @@ -16,13 +16,26 @@ Gem::Specification.new do |s| s.summary = "Provides lexical scanning operations on a String." s.description = "Provides lexical scanning operations on a String." - s.require_path = %w{lib} - s.files = %w{ext/strscan/extconf.rb ext/strscan/strscan.c} - s.extensions = %w{ext/strscan/extconf.rb} + files = [ + "COPYING", + "LICENSE.txt", + ] + if RUBY_ENGINE == "jruby" + s.require_paths = %w{ext/jruby/lib lib} + files << "ext/jruby/lib/strscan.rb" + files << "lib/strscan.jar" + s.platform = "java" + else + s.require_paths = %w{lib} + files << "ext/strscan/extconf.rb" + files << "ext/strscan/strscan.c" + s.extensions = %w{ext/strscan/extconf.rb} + end + s.files = files s.required_ruby_version = ">= 2.4.0" - s.authors = ["Minero Aoki", "Sutou Kouhei"] - s.email = [nil, "[email protected]"] + s.authors = ["Minero Aoki", "Sutou Kouhei", "Charles Oliver Nutter"] + s.email = [nil, "[email protected]", "[email protected]"] s.homepage = "https://github.com/ruby/strscan" s.licenses = ["Ruby", "BSD-2-Clause"] end diff --git a/test/strscan/test_ractor.rb b/test/strscan/test_ractor.rb index 480c1ae8a6..a5de7e56ed 100644 --- a/test/strscan/test_ractor.rb +++ b/test/strscan/test_ractor.rb @@ -3,7 +3,7 @@ require 'test/unit' class TestStringScannerRactor < Test::Unit::TestCase def setup - pend unless defined? Ractor + omit "Ractor not defined" unless defined? Ractor end def test_ractor diff --git a/test/strscan/test_stringscanner.rb b/test/strscan/test_stringscanner.rb index 6e30be1f7d..2fb8a17062 100644 --- a/test/strscan/test_stringscanner.rb +++ b/test/strscan/test_stringscanner.rb @@ -207,6 +207,8 @@ class TestStringScanner < Test::Unit::TestCase end def test_charpos_not_use_string_methods + omit "not supported on TruffleRuby" if RUBY_ENGINE == "truffleruby" + string = +'abcädeföghi' scanner = create_string_scanner(string) @@ -567,6 +569,8 @@ class TestStringScanner < Test::Unit::TestCase end def test_invalid_encoding_string + omit "no encoding check on TruffleRuby for scan(String)" if RUBY_ENGINE == "truffleruby" + str = "\xA1\xA2".dup.force_encoding("euc-jp") ss = create_string_scanner(str) assert_raise(Encoding::CompatibilityError) do @@ -712,6 +716,8 @@ class TestStringScanner < Test::Unit::TestCase end def test_aref_without_regex + omit "#[:missing] always raises on TruffleRuby if matched" if RUBY_ENGINE == "truffleruby" + s = create_string_scanner('abc') s.get_byte assert_nil(s[:c]) @@ -757,6 +763,33 @@ class TestStringScanner < Test::Unit::TestCase assert_equal(false, StringScanner.new("a", fixed_anchor: nil).fixed_anchor?) assert_equal(false, StringScanner.new("a", fixed_anchor: false).fixed_anchor?) end + + def test_scan_aref_repeatedly + s = StringScanner.new('test string') + assert_equal "test", s.scan(/\w(\w)(\w*)/) + assert_equal "test", s[0] + assert_equal "e", s[1] + assert_equal "st", s[2] + assert_nil s.scan(/\w+/) + assert_nil s[0] + assert_nil s[1] + assert_nil s[2] + assert_equal " ", s.scan(/\s+/) + assert_equal " ", s[0] + assert_nil s[1] + assert_nil s[2] + assert_equal "string", s.scan(/\w(\w)(\w*)/) + assert_equal "string", s[0] + assert_equal "t", s[1] + assert_equal "ring", s[2] + end + + def test_named_captures + omit("not implemented on TruffleRuby") if ["truffleruby"].include?(RUBY_ENGINE) + scan = StringScanner.new("foobarbaz") + assert_equal(9, scan.match?(/(?<f>foo)(?<r>bar)(?<z>baz)/)) + assert_equal({"f" => "foo", "r" => "bar", "z" => "baz"}, scan.named_captures) + end end class TestStringScannerFixedAnchor < TestStringScanner |