diff --git a/ext/jruby/org/jruby/ext/strscan/RubyStringScanner.java b/ext/jruby/org/jruby/ext/strscan/RubyStringScanner.java index 9d5acce28c..ffdb761684 100644 --- a/ext/jruby/org/jruby/ext/strscan/RubyStringScanner.java +++ b/ext/jruby/org/jruby/ext/strscan/RubyStringScanner.java @@ -236,8 +236,12 @@ public IRubyObject charpos(ThreadContext context) { ByteList strBL = str.getByteList(); int strBeg = strBL.begin(); + int strSize = strBL.getRealSize(); + int pos = curr; + + if (pos > strSize) pos = strSize; - return runtime.newFixnum(StringSupport.strLength(strBL.getEncoding(), strBL.unsafeBytes(), strBeg, strBeg + curr)); + return runtime.newFixnum(StringSupport.strLength(strBL.getEncoding(), strBL.unsafeBytes(), strBeg, strBeg + pos)); } private IRubyObject extractRange(Ruby runtime, int beg, int end) { diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c index 81e6b14cf8..ec8f5e23ff 100644 --- a/ext/strscan/strscan.c +++ b/ext/strscan/strscan.c @@ -79,7 +79,7 @@ struct strscanner #define CURPTR(s) (S_PBEG(s) + (s)->curr) #define S_RESTLEN(s) (S_LEN(s) - (s)->curr) -#define EOS_P(s) ((s)->curr >= RSTRING_LEN(p->str)) +#define EOS_P(s) ((s)->curr >= RSTRING_LEN((s)->str)) #define GET_SCANNER(obj,var) do {\ (var) = check_strscan(obj);\ @@ -573,10 +573,12 @@ static VALUE strscan_get_charpos(VALUE self) { struct strscanner *p; + const char *s; GET_SCANNER(self, p); - return LONG2NUM(rb_enc_strlen(S_PBEG(p), CURPTR(p), rb_enc_get(p->str))); + s = EOS_P(p) ? S_PEND(p) : CURPTR(p); + return LONG2NUM(rb_enc_strlen(S_PBEG(p), s, rb_enc_get(p->str))); } /* diff --git a/lib/strscan/truffleruby.rb b/lib/strscan/truffleruby.rb index c95f2d0987..f6e6513781 100644 --- a/lib/strscan/truffleruby.rb +++ b/lib/strscan/truffleruby.rb @@ -59,7 +59,7 @@ def pos=(new_pos) end alias_method :pointer=, :pos= - def charpos = Primitive.string_byte_index_to_character_index(@string, @pos) + def charpos = (eos? ? @string.size : Primitive.string_byte_index_to_character_index(@string, @pos)) def rest = @string.byteslice(@pos, @string.bytesize) diff --git a/test/strscan/test_stringscanner.rb b/test/strscan/test_stringscanner.rb index 47b1e2a155..79784b59f5 100644 --- a/test/strscan/test_stringscanner.rb +++ b/test/strscan/test_stringscanner.rb @@ -231,6 +231,14 @@ class << string assert_equal(8, scanner.charpos) end + def test_charpos_when_shrunk + s = "\u{e9}" * 64 + sc = StringScanner.new(s) + sc.scan(/(?:\u{e9})+/) + s.replace("z") + assert_equal(s.length, sc.charpos) + end + def test_concat s = create_string_scanner('a'.dup) s.scan(/a/)