summaryrefslogtreecommitdiff
diff options
authorHiroshi SHIBATA <[email protected]>2022-12-09 13:03:33 +0900
committerHiroshi SHIBATA <[email protected]>2022-12-09 16:36:22 +0900
commit4e31fea77d360c6535e33ff2525d80fba38d15d8 (patch)
tree92bdeec2cadb323f10197d1013c699589feb83d0
parentbcf01b18cfe9b21bfde32e28edd4745703bf190c (diff)
Merge strscan-3.0.5
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/6890
-rw-r--r--ext/strscan/extconf.rb10
-rw-r--r--ext/strscan/strscan.c64
-rw-r--r--ext/strscan/strscan.gemspec23
-rw-r--r--test/strscan/test_ractor.rb2
-rw-r--r--test/strscan/test_stringscanner.rb33
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