Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion ext/jruby/org/jruby/ext/strscan/RubyStringScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,15 @@ public IRubyObject matched(ThreadContext context) {
public IRubyObject matched_size(ThreadContext context) {
check(context);
if (!isMatched()) return context.nil;
return RubyFixnum.newFixnum(context.runtime, regs.getEnd(0) - regs.getBeg(0));

int size = str.size();
int beg = adjustRegisterPosition(regs.getBeg(0));
int end = adjustRegisterPosition(regs.getEnd(0));

if (beg > size) return context.nil;
if (end > size) end = size;

return RubyFixnum.newFixnum(context.runtime, end - beg);
}

@JRubyMethod(name = "[]")
Expand Down
6 changes: 5 additions & 1 deletion ext/strscan/strscan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1673,10 +1673,14 @@ static VALUE
strscan_matched_size(VALUE self)
{
struct strscanner *p;
long beg, end;

GET_SCANNER(self, p);
if (! MATCHED_P(p)) return Qnil;
return LONG2NUM(p->regs.end[0] - p->regs.beg[0]);
beg = adjust_register_position(p, p->regs.beg[0]);
if (beg > S_LEN(p)) return Qnil;
end = minl(adjust_register_position(p, p->regs.end[0]), S_LEN(p));
return LONG2NUM(end - beg);
}

static int
Expand Down
14 changes: 12 additions & 2 deletions lib/strscan/truffleruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,15 @@ def rest?

def matched? = !Primitive.nil?(@last_match)

def matched = @last_match&.to_s
def matched
return unless @last_match

beg = Primitive.match_data_byte_begin(@last_match, 0)
return if beg > @string.bytesize

fin = [Primitive.match_data_byte_end(@last_match, 0), @string.bytesize].min
@string.byteslice(beg, fin - beg)
end

def [](group)
raise TypeError, 'no implicit conversion of Range into Integer' if Primitive.is_a?(group, Range)
Expand Down Expand Up @@ -151,7 +159,9 @@ def named_captures = @last_match&.named_captures || {}

def matched_size
if @last_match
Primitive.match_data_byte_end(@last_match, 0) - Primitive.match_data_byte_begin(@last_match, 0)
beg = Primitive.match_data_byte_begin(@last_match, 0)
return if beg > @string.bytesize
[Primitive.match_data_byte_end(@last_match, 0), @string.bytesize].min - beg
end
end

Expand Down
21 changes: 21 additions & 0 deletions test/strscan/test_stringscanner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,27 @@ def test_matched_size
assert_nil(s.matched_size)
end

def test_matched_size_when_shrunk
# matched_size must agree with matched, which extract_range clamps to the
# current length of the stored string.
s = create_string_scanner(+"before 29 after")
s.skip_until(" ")
assert_equal("29", s.scan(/\d+/))
assert_equal(2, s.matched_size)

s.string.replace("before 2")
assert_equal("2", s.matched)
assert_equal(1, s.matched_size)

s.string.replace("before ")
assert_equal("", s.matched)
assert_equal(0, s.matched_size)

s.string.replace("before")
assert_nil(s.matched)
assert_nil(s.matched_size)
end

def test_empty_encoding_utf8
ss = create_string_scanner('')
assert_equal(Encoding::UTF_8, ss.rest.encoding)
Expand Down