Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 083290adc3b6
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: c24f7fa865d9
Choose a head ref
  • 3 commits
  • 3 files changed
  • 1 contributor

Commits on Jun 23, 2017

  1. Copy the full SHA
    1cd660b View commit details
  2. Copy the full SHA
    a6a1466 View commit details
  3. fix String#rindex not working properly in specific UTF-8 case at #3396

    upper bound check should not halt the loop since we're going pos--
    (and there's a chance were able to find a match at a lower position)
    kares committed Jun 23, 2017
    Copy the full SHA
    c24f7fa View commit details
Showing with 66 additions and 70 deletions.
  1. +32 −32 core/src/main/java/org/jruby/RubyString.java
  2. +18 −26 core/src/main/java/org/jruby/util/StringSupport.java
  3. +16 −12 test/jruby/test_pathname.rb
64 changes: 32 additions & 32 deletions core/src/main/java/org/jruby/RubyString.java
Original file line number Diff line number Diff line change
@@ -2766,39 +2766,40 @@ private int strseqIndex(final RubyString sub, int offset, boolean inBytes) {
return pos + offset;
}

/** rb_str_rindex_m
*
*/
public IRubyObject rindex(ThreadContext context, IRubyObject arg0) {
return rindex19(context, arg0);
@Deprecated
public IRubyObject rindex19(ThreadContext context, IRubyObject arg0) {
return rindex(context, arg0);
}

public IRubyObject rindex(ThreadContext context, IRubyObject arg0, IRubyObject arg1) {
return rindex19(context, arg0, arg1);
@Deprecated
public IRubyObject rindex19(ThreadContext context, IRubyObject arg0, IRubyObject arg1) {
return rindex(context, arg0, arg1);
}

/** rb_str_rindex_m
*
*/
@JRubyMethod(name = "rindex", reads = BACKREF, writes = BACKREF)
public IRubyObject rindex19(ThreadContext context, IRubyObject arg0) {
return rindexCommon19(context.runtime, context, arg0, strLength());
public IRubyObject rindex(ThreadContext context, IRubyObject arg0) {
return rindexCommon(context, arg0, strLength());
}

@JRubyMethod(name = "rindex", reads = BACKREF, writes = BACKREF)
public IRubyObject rindex19(ThreadContext context, IRubyObject arg0, IRubyObject arg1) {
public IRubyObject rindex(ThreadContext context, IRubyObject arg0, IRubyObject arg1) {
int pos = RubyNumeric.num2int(arg1);
Ruby runtime = context.runtime;
int length = strLength();
if (pos < 0) {
pos += length;
if (pos < 0) {
if (arg0 instanceof RubyRegexp) context.setBackRef(runtime.getNil());
return runtime.getNil();
if (arg0 instanceof RubyRegexp) context.setBackRef(context.nil);
return context.nil;
}
}
if (pos > length) pos = length;
return rindexCommon19(runtime, context, arg0, pos);
return rindexCommon(context, arg0, pos);
}

private IRubyObject rindexCommon19(Ruby runtime, ThreadContext context, final IRubyObject sub, int pos) {
private IRubyObject rindexCommon(ThreadContext context, final IRubyObject sub, int pos) {
if (sub instanceof RubyRegexp) {
RubyRegexp regSub = (RubyRegexp) sub;
pos = StringSupport.offset(
@@ -2809,25 +2810,24 @@ private IRubyObject rindexCommon19(Ruby runtime, ThreadContext context, final IR
pos = subLength(pos);
}
} else if (sub instanceof RubyString) {
Encoding enc = this.checkEncoding((RubyString) sub);
pos = StringSupport.rindex(
value,
StringSupport.strLengthFromRubyString(
this,
enc),
StringSupport.strLengthFromRubyString(
((RubyString) sub),
enc),
pos,
(RubyString) sub,
this.checkEncoding((RubyString) sub));
Encoding enc = checkEncoding((RubyString) sub);
pos = StringSupport.rindex(value,
StringSupport.strLengthFromRubyString(this, enc),
StringSupport.strLengthFromRubyString(((RubyString) sub), enc),
pos, (RubyString) sub, enc
);
} else {
IRubyObject tmp = sub.checkStringType();
if (tmp.isNil()) throw runtime.newTypeError("type mismatch: " + sub.getMetaClass().getName() + " given");
pos = StringSupport.rindex(value, StringSupport.strLengthFromRubyString(this, this.checkEncoding((RubyString) tmp)), StringSupport.strLengthFromRubyString(((RubyString) tmp), this.checkEncoding((RubyString) tmp)), pos, (RubyString) tmp, this.checkEncoding((RubyString) tmp));
}
if (pos >= 0) return RubyFixnum.newFixnum(runtime, pos);
return runtime.getNil();
if (tmp.isNil()) throw context.runtime.newTypeError("type mismatch: " + sub.getMetaClass().getName() + " given");
Encoding enc = checkEncoding((RubyString) tmp);
pos = StringSupport.rindex(value,
StringSupport.strLengthFromRubyString(this, enc),
StringSupport.strLengthFromRubyString(((RubyString) tmp), enc),
pos, (RubyString) tmp, enc
);
}
if (pos >= 0) return RubyFixnum.newFixnum(context.runtime, pos);
return context.nil;
}

@Deprecated
44 changes: 18 additions & 26 deletions core/src/main/java/org/jruby/util/StringSupport.java
Original file line number Diff line number Diff line change
@@ -965,48 +965,40 @@ public static int rindex(ByteList source, int sourceChars, int subChars, int pos

final ByteList subString = subStringCodeRangeable.getByteList();

int sourceSize = source.realSize();
int subSize = subString.realSize();
final int srcLen = source.getRealSize();
final int subLen = subString.getRealSize();

if (sourceChars < subChars || sourceSize < subSize) return -1;
if (sourceChars < subChars || srcLen < subLen) return -1;
if (sourceChars - pos < subChars) pos = sourceChars - subChars;
if (sourceChars == 0) return pos;

byte[] sourceBytes = source.getUnsafeBytes();
int sbeg = source.getBegin();
int end = sbeg + source.getRealSize();
byte[] srcBytes = source.getUnsafeBytes();
final int srcBeg = source.getBegin();

if (pos == 0) {
if (ByteList.memcmp(sourceBytes, sbeg, subString.getUnsafeBytes(), subString.begin(), subString.getRealSize()) == 0) {
if (ByteList.memcmp(srcBytes, srcBeg, subString.getUnsafeBytes(), subString.getBegin(), subLen) == 0) {
return 0;
} else {
return -1;
}
return -1;
}

int s = nth(enc, sourceBytes, sbeg, end, pos);

return strRindex(source, subString, s, pos, enc);
int s = nth(enc, srcBytes, srcBeg, srcBeg + srcLen, pos);
return strRindex(srcBytes, srcBeg, srcLen, subString.getUnsafeBytes(), subString.getBegin(), subLen, s, pos, enc);
}

private static int strRindex(ByteList str, ByteList sub, int s, int pos, Encoding enc) {
int slen;
byte[] strBytes = str.unsafeBytes();
byte[] subBytes = sub.unsafeBytes();
int sbeg, e, t;
private static int strRindex(final byte[] strBytes, final int strBeg, final int strLen,
final byte[] subBytes, final int subBeg, final int subLen,
int s, int pos, final Encoding enc) {

sbeg = str.begin();
e = str.begin() + str.realSize();
t = sub.begin();
slen = sub.realSize();
final int e = strBeg + strLen;

while (s >= sbeg && s + slen <= sbeg + str.realSize()) {
if (ByteList.memcmp(strBytes, s, subBytes, t, slen) == 0) {
while (s >= strBeg) {
if (s + subLen <= e && ByteList.memcmp(strBytes, s, subBytes, subBeg, subLen) == 0) {
return pos;
}
if (pos == 0) break;
pos--;
s = enc.prevCharHead(strBytes, sbeg, s, e);
if (pos == 0) break; pos--;
s = enc.prevCharHead(strBytes, strBeg, s, e);
}

return -1;
28 changes: 16 additions & 12 deletions test/jruby/test_pathname.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# encoding: UTF-8
require 'test/unit'
require 'pathname'
require 'rbconfig'
require 'tempfile'

class TestPathname < Test::Unit::TestCase
WINDOWS = RbConfig::CONFIG['host_os'] =~ /Windows|mswin/
@@ -10,17 +10,15 @@ def test_dup
assert_equal 'some/path', Pathname.new('some/path').dup.to_s
end

unless WINDOWS # Don't have symlinks on Windows.
def test_realpath_symlink
target = Tempfile.new 'target'
link = Dir::Tmpname.make_tmpname 'link', nil
File.symlink(target, link)
assert_equal Pathname.new(target).realpath, Pathname.new(link).realpath
ensure
target.close! if target
File.delete(link) if link && File.exists?(link)
end
end
def test_realpath_symlink; require 'tempfile'
target = Tempfile.new 'target'
link = Dir::Tmpname.make_tmpname 'link', nil
File.symlink(target, link)
assert_equal Pathname.new(target).realpath, Pathname.new(link).realpath
ensure
target.close! if target
File.delete(link) if link && File.exists?(link)
end unless WINDOWS # Don't have symlinks on Windows.

# GH-3392
def test_dirname_ending_in_!
@@ -67,4 +65,10 @@ def test_absolute
assert Pathname.new('my.jar!/asd').absolute?
end

def test_unicode_name
x = "joe"
y = "joe/⸀䐀攀氀攀琀攀䴀攀/fred"
puts Pathname.new(y).relative_path_from(Pathname.new(x))
end

end