mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
Merge strscan-3.0.7
This commit is contained in:
parent
30379fa1e2
commit
64d93539e7
3 changed files with 107 additions and 63 deletions
|
@ -3,6 +3,7 @@ require 'mkmf'
|
|||
if RUBY_ENGINE == 'ruby'
|
||||
$INCFLAGS << " -I$(top_srcdir)" if $extmk
|
||||
have_func("onig_region_memsize", "ruby.h")
|
||||
have_func("rb_reg_onig_match", "ruby.h")
|
||||
create_makefile 'strscan'
|
||||
else
|
||||
File.write('Makefile', dummy_makefile("").join)
|
||||
|
|
|
@ -22,7 +22,7 @@ extern size_t onig_region_memsize(const struct re_registers *regs);
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define STRSCAN_VERSION "3.0.6"
|
||||
#define STRSCAN_VERSION "3.0.7"
|
||||
|
||||
/* =======================================================================
|
||||
Data Type Definitions
|
||||
|
@ -539,6 +539,68 @@ adjust_register_position(struct strscanner *p, long position)
|
|||
}
|
||||
}
|
||||
|
||||
/* rb_reg_onig_match is available in Ruby 3.3 and later. */
|
||||
#ifndef HAVE_RB_REG_ONIG_MATCH
|
||||
static OnigPosition
|
||||
rb_reg_onig_match(VALUE re, VALUE str,
|
||||
OnigPosition (*match)(regex_t *reg, VALUE str, struct re_registers *regs, void *args),
|
||||
void *args, struct re_registers *regs)
|
||||
{
|
||||
regex_t *reg = rb_reg_prepare_re(re, str);
|
||||
|
||||
bool tmpreg = reg != RREGEXP_PTR(re);
|
||||
if (!tmpreg) RREGEXP(re)->usecnt++;
|
||||
|
||||
OnigPosition result = match(reg, str, regs, args);
|
||||
|
||||
if (!tmpreg) RREGEXP(re)->usecnt--;
|
||||
if (tmpreg) {
|
||||
if (RREGEXP(re)->usecnt) {
|
||||
onig_free(reg);
|
||||
}
|
||||
else {
|
||||
onig_free(RREGEXP_PTR(re));
|
||||
RREGEXP_PTR(re) = reg;
|
||||
}
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
if (result != ONIG_MISMATCH) {
|
||||
rb_raise(ScanError, "regexp buffer overflow");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
static OnigPosition
|
||||
strscan_match(regex_t *reg, VALUE str, struct re_registers *regs, void *args_ptr)
|
||||
{
|
||||
struct strscanner *p = (struct strscanner *)args_ptr;
|
||||
|
||||
return onig_match(reg,
|
||||
match_target(p),
|
||||
(UChar* )(CURPTR(p) + S_RESTLEN(p)),
|
||||
(UChar* )CURPTR(p),
|
||||
regs,
|
||||
ONIG_OPTION_NONE);
|
||||
}
|
||||
|
||||
static OnigPosition
|
||||
strscan_search(regex_t *reg, VALUE str, struct re_registers *regs, void *args_ptr)
|
||||
{
|
||||
struct strscanner *p = (struct strscanner *)args_ptr;
|
||||
|
||||
return onig_search(reg,
|
||||
match_target(p),
|
||||
(UChar *)(CURPTR(p) + S_RESTLEN(p)),
|
||||
(UChar *)CURPTR(p),
|
||||
(UChar *)(CURPTR(p) + S_RESTLEN(p)),
|
||||
regs,
|
||||
ONIG_OPTION_NONE);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
strscan_do_scan(VALUE self, VALUE pattern, int succptr, int getstr, int headonly)
|
||||
{
|
||||
|
@ -560,47 +622,14 @@ strscan_do_scan(VALUE self, VALUE pattern, int succptr, int getstr, int headonly
|
|||
}
|
||||
|
||||
if (RB_TYPE_P(pattern, T_REGEXP)) {
|
||||
regex_t *rb_reg_prepare_re(VALUE re, VALUE str);
|
||||
regex_t *re;
|
||||
long ret;
|
||||
int tmpreg;
|
||||
|
||||
p->regex = pattern;
|
||||
re = rb_reg_prepare_re(pattern, p->str);
|
||||
tmpreg = re != RREGEXP_PTR(pattern);
|
||||
if (!tmpreg) RREGEXP(pattern)->usecnt++;
|
||||
OnigPosition ret = rb_reg_onig_match(pattern,
|
||||
p->str,
|
||||
headonly ? strscan_match : strscan_search,
|
||||
(void *)p,
|
||||
&(p->regs));
|
||||
|
||||
if (headonly) {
|
||||
ret = onig_match(re,
|
||||
match_target(p),
|
||||
(UChar* )(CURPTR(p) + S_RESTLEN(p)),
|
||||
(UChar* )CURPTR(p),
|
||||
&(p->regs),
|
||||
ONIG_OPTION_NONE);
|
||||
}
|
||||
else {
|
||||
ret = onig_search(re,
|
||||
match_target(p),
|
||||
(UChar* )(CURPTR(p) + S_RESTLEN(p)),
|
||||
(UChar* )CURPTR(p),
|
||||
(UChar* )(CURPTR(p) + S_RESTLEN(p)),
|
||||
&(p->regs),
|
||||
ONIG_OPTION_NONE);
|
||||
}
|
||||
if (!tmpreg) RREGEXP(pattern)->usecnt--;
|
||||
if (tmpreg) {
|
||||
if (RREGEXP(pattern)->usecnt) {
|
||||
onig_free(re);
|
||||
}
|
||||
else {
|
||||
onig_free(RREGEXP_PTR(pattern));
|
||||
RREGEXP_PTR(pattern) = re;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == -2) rb_raise(ScanError, "regexp buffer overflow");
|
||||
if (ret < 0) {
|
||||
/* not matched */
|
||||
if (ret == ONIG_MISMATCH) {
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
|
@ -1502,7 +1531,9 @@ strscan_named_captures(VALUE self)
|
|||
named_captures_data data;
|
||||
data.self = self;
|
||||
data.captures = rb_hash_new();
|
||||
onig_foreach_name(RREGEXP_PTR(p->regex), named_captures_iter, &data);
|
||||
if (!RB_NIL_P(p->regex)) {
|
||||
onig_foreach_name(RREGEXP_PTR(p->regex), named_captures_iter, &data);
|
||||
}
|
||||
|
||||
return data.captures;
|
||||
}
|
||||
|
|
|
@ -7,11 +7,7 @@
|
|||
require 'strscan'
|
||||
require 'test/unit'
|
||||
|
||||
class TestStringScanner < Test::Unit::TestCase
|
||||
def create_string_scanner(string, *args)
|
||||
StringScanner.new(string, *args)
|
||||
end
|
||||
|
||||
module StringScannerTests
|
||||
def test_s_new
|
||||
s = create_string_scanner('test string')
|
||||
assert_instance_of StringScanner, s
|
||||
|
@ -155,8 +151,10 @@ class TestStringScanner < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_string
|
||||
s = create_string_scanner('test')
|
||||
assert_equal 'test', s.string
|
||||
s = create_string_scanner('test string')
|
||||
assert_equal 'test string', s.string
|
||||
s.scan(/test/)
|
||||
assert_equal 'test string', s.string
|
||||
s.string = 'a'
|
||||
assert_equal 'a', s.string
|
||||
s.scan(/a/)
|
||||
|
@ -467,7 +465,10 @@ class TestStringScanner < Test::Unit::TestCase
|
|||
assert_equal 'foo', s['a']
|
||||
assert_equal 'bar', s['b']
|
||||
assert_raise(IndexError) { s['c'] }
|
||||
assert_raise_with_message(IndexError, /\u{30c6 30b9 30c8}/) { s["\u{30c6 30b9 30c8}"] }
|
||||
# see https://github.com/jruby/jruby/issues/7644
|
||||
unless RUBY_ENGINE == "jruby" && RbConfig::CONFIG['host_os'] =~ /mswin|win32|mingw/
|
||||
assert_raise_with_message(IndexError, /\u{30c6 30b9 30c8}/) { s["\u{30c6 30b9 30c8}"] }
|
||||
end
|
||||
end
|
||||
|
||||
def test_pre_match
|
||||
|
@ -751,19 +752,6 @@ class TestStringScanner < Test::Unit::TestCase
|
|||
assert_nil(s.values_at(0, -1, 5, 2))
|
||||
end
|
||||
|
||||
def test_fixed_anchor_true
|
||||
assert_equal(true, StringScanner.new("a", fixed_anchor: true).fixed_anchor?)
|
||||
end
|
||||
|
||||
def test_fixed_anchor_false
|
||||
assert_equal(false, StringScanner.new("a").fixed_anchor?)
|
||||
assert_equal(false, StringScanner.new("a", true).fixed_anchor?)
|
||||
assert_equal(false, StringScanner.new("a", false).fixed_anchor?)
|
||||
assert_equal(false, StringScanner.new("a", {}).fixed_anchor?)
|
||||
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*)/)
|
||||
|
@ -787,12 +775,36 @@ class TestStringScanner < Test::Unit::TestCase
|
|||
def test_named_captures
|
||||
omit("not implemented on TruffleRuby") if ["truffleruby"].include?(RUBY_ENGINE)
|
||||
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)
|
||||
end
|
||||
end
|
||||
|
||||
class TestStringScannerFixedAnchor < TestStringScanner
|
||||
class TestStringScanner < Test::Unit::TestCase
|
||||
include StringScannerTests
|
||||
|
||||
def create_string_scanner(string, *args)
|
||||
StringScanner.new(string, *args)
|
||||
end
|
||||
|
||||
def test_fixed_anchor_true
|
||||
assert_equal(true, StringScanner.new("a", fixed_anchor: true).fixed_anchor?)
|
||||
end
|
||||
|
||||
def test_fixed_anchor_false
|
||||
assert_equal(false, StringScanner.new("a").fixed_anchor?)
|
||||
assert_equal(false, StringScanner.new("a", true).fixed_anchor?)
|
||||
assert_equal(false, StringScanner.new("a", false).fixed_anchor?)
|
||||
assert_equal(false, StringScanner.new("a", {}).fixed_anchor?)
|
||||
assert_equal(false, StringScanner.new("a", fixed_anchor: nil).fixed_anchor?)
|
||||
assert_equal(false, StringScanner.new("a", fixed_anchor: false).fixed_anchor?)
|
||||
end
|
||||
end
|
||||
|
||||
class TestStringScannerFixedAnchor < Test::Unit::TestCase
|
||||
include StringScannerTests
|
||||
|
||||
def create_string_scanner(string, *args)
|
||||
StringScanner.new(string, fixed_anchor: true)
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue