Merge strscan-3.0.5

This commit is contained in:
Hiroshi SHIBATA 2022-12-09 13:03:33 +09:00
parent bcf01b18cf
commit 4e31fea77d
Notes: git 2022-12-09 07:36:48 +00:00
5 changed files with 117 additions and 15 deletions

View File

@ -1,5 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'mkmf' require 'mkmf'
if RUBY_ENGINE == 'ruby'
$INCFLAGS << " -I$(top_srcdir)" if $extmk $INCFLAGS << " -I$(top_srcdir)" if $extmk
have_func("onig_region_memsize", "ruby.h") have_func("onig_region_memsize", "ruby.h")
create_makefile 'strscan' create_makefile 'strscan'
else
File.write('Makefile', dummy_makefile("").join)
end

View File

@ -22,7 +22,7 @@ extern size_t onig_region_memsize(const struct re_registers *regs);
#include <stdbool.h> #include <stdbool.h>
#define STRSCAN_VERSION "3.0.1" #define STRSCAN_VERSION "3.0.5"
/* ======================================================================= /* =======================================================================
Data Type Definitions Data Type Definitions
@ -435,9 +435,9 @@ strscan_get_pos(VALUE self)
* *
* In short, it's a 0-based index into the string. * In short, it's a 0-based index into the string.
* *
* s = StringScanner.new("abcädeföghi") * s = StringScanner.new("abc\u00e4def\u00f6ghi")
* s.charpos # -> 0 * s.charpos # -> 0
* s.scan_until(/ä/) # -> "abcä" * s.scan_until(/\u00e4/) # -> "abc\u00E4"
* s.pos # -> 5 * s.pos # -> 5
* s.charpos # -> 4 * s.charpos # -> 4
*/ */
@ -1458,6 +1458,54 @@ strscan_fixed_anchor_p(VALUE self)
return p->fixed_anchor_p ? Qtrue : Qfalse; 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 Ruby Interface
======================================================================= */ ======================================================================= */
@ -1468,6 +1516,8 @@ strscan_fixed_anchor_p(VALUE self)
* StringScanner provides for lexical scanning operations on a String. Here is * StringScanner provides for lexical scanning operations on a String. Here is
* an example of its usage: * an example of its usage:
* *
* require 'strscan'
*
* s = StringScanner.new('This is an example string') * s = StringScanner.new('This is an example string')
* s.eos? # -> false * s.eos? # -> false
* *
@ -1650,4 +1700,6 @@ Init_strscan(void)
rb_define_method(StringScanner, "inspect", strscan_inspect, 0); rb_define_method(StringScanner, "inspect", strscan_inspect, 0);
rb_define_method(StringScanner, "fixed_anchor?", strscan_fixed_anchor_p, 0); rb_define_method(StringScanner, "fixed_anchor?", strscan_fixed_anchor_p, 0);
rb_define_method(StringScanner, "named_captures", strscan_named_captures, 0);
} }

View File

@ -16,13 +16,26 @@ Gem::Specification.new do |s|
s.summary = "Provides lexical scanning operations on a String." s.summary = "Provides lexical scanning operations on a String."
s.description = "Provides lexical scanning operations on a String." s.description = "Provides lexical scanning operations on a String."
s.require_path = %w{lib} files = [
s.files = %w{ext/strscan/extconf.rb ext/strscan/strscan.c} "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} s.extensions = %w{ext/strscan/extconf.rb}
end
s.files = files
s.required_ruby_version = ">= 2.4.0" s.required_ruby_version = ">= 2.4.0"
s.authors = ["Minero Aoki", "Sutou Kouhei"] s.authors = ["Minero Aoki", "Sutou Kouhei", "Charles Oliver Nutter"]
s.email = [nil, "kou@cozmixng.org"] s.email = [nil, "kou@cozmixng.org", "headius@headius.com"]
s.homepage = "https://github.com/ruby/strscan" s.homepage = "https://github.com/ruby/strscan"
s.licenses = ["Ruby", "BSD-2-Clause"] s.licenses = ["Ruby", "BSD-2-Clause"]
end end

View File

@ -3,7 +3,7 @@ require 'test/unit'
class TestStringScannerRactor < Test::Unit::TestCase class TestStringScannerRactor < Test::Unit::TestCase
def setup def setup
pend unless defined? Ractor omit "Ractor not defined" unless defined? Ractor
end end
def test_ractor def test_ractor

View File

@ -207,6 +207,8 @@ class TestStringScanner < Test::Unit::TestCase
end end
def test_charpos_not_use_string_methods def test_charpos_not_use_string_methods
omit "not supported on TruffleRuby" if RUBY_ENGINE == "truffleruby"
string = +'abcädeföghi' string = +'abcädeföghi'
scanner = create_string_scanner(string) scanner = create_string_scanner(string)
@ -567,6 +569,8 @@ class TestStringScanner < Test::Unit::TestCase
end end
def test_invalid_encoding_string 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") str = "\xA1\xA2".dup.force_encoding("euc-jp")
ss = create_string_scanner(str) ss = create_string_scanner(str)
assert_raise(Encoding::CompatibilityError) do assert_raise(Encoding::CompatibilityError) do
@ -712,6 +716,8 @@ class TestStringScanner < Test::Unit::TestCase
end end
def test_aref_without_regex def test_aref_without_regex
omit "#[:missing] always raises on TruffleRuby if matched" if RUBY_ENGINE == "truffleruby"
s = create_string_scanner('abc') s = create_string_scanner('abc')
s.get_byte s.get_byte
assert_nil(s[:c]) 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: nil).fixed_anchor?)
assert_equal(false, StringScanner.new("a", fixed_anchor: false).fixed_anchor?) assert_equal(false, StringScanner.new("a", fixed_anchor: false).fixed_anchor?)
end 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 end
class TestStringScannerFixedAnchor < TestStringScanner class TestStringScannerFixedAnchor < TestStringScanner