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: 53cf12a5721d
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: cd3ab2c06e2e
Choose a head ref
  • 2 commits
  • 4 files changed
  • 1 contributor

Commits on Apr 2, 2015

  1. Copy the full SHA
    613aa3e View commit details
  2. Copy the full SHA
    cd3ab2c View commit details
45 changes: 6 additions & 39 deletions core/src/main/java/org/jruby/RubyString.java
Original file line number Diff line number Diff line change
@@ -1508,51 +1508,18 @@ public IRubyObject casecmp19(ThreadContext context, IRubyObject other) {
if (singleByteOptimizable() && otherStr.singleByteOptimizable()) {
return RubyFixnum.newFixnum(runtime, value.caseInsensitiveCmp(otherStr.value));
} else {
return multiByteCasecmp(runtime, enc, value, otherStr.value);
}
}

private IRubyObject multiByteCasecmp(Ruby runtime, Encoding enc, ByteList value, ByteList otherValue) {
byte[]bytes = value.getUnsafeBytes();
int p = value.getBegin();
int end = p + value.getRealSize();

byte[]obytes = otherValue.getUnsafeBytes();
int op = otherValue.getBegin();
int oend = op + otherValue.getRealSize();
final int ret = StringSupport.multiByteCasecmp(enc, value, otherStr.value);

while (p < end && op < oend) {
final int c, oc;
if (enc.isAsciiCompatible()) {
c = bytes[p] & 0xff;
oc = obytes[op] & 0xff;
} else {
c = StringSupport.preciseCodePoint(enc, bytes, p, end);
oc = StringSupport.preciseCodePoint(enc, obytes, op, oend);
if (ret < 0) {
return RubyFixnum.minus_one(runtime);
}

int cl, ocl;
if (enc.isAsciiCompatible() && Encoding.isAscii(c) && Encoding.isAscii(oc)) {
byte uc = AsciiTables.ToUpperCaseTable[c];
byte uoc = AsciiTables.ToUpperCaseTable[oc];
if (uc != uoc) {
return uc < uoc ? RubyFixnum.minus_one(runtime) : RubyFixnum.one(runtime);
}
cl = ocl = 1;
} else {
cl = StringSupport.length(enc, bytes, p, end);
ocl = StringSupport.length(enc, obytes, op, oend);
// TODO: opt for 2 and 3 ?
int ret = StringSupport.caseCmp(bytes, p, obytes, op, cl < ocl ? cl : ocl);
if (ret != 0) return ret < 0 ? RubyFixnum.minus_one(runtime) : RubyFixnum.one(runtime);
if (cl != ocl) return cl < ocl ? RubyFixnum.minus_one(runtime) : RubyFixnum.one(runtime);
if (ret > 0) {
return RubyFixnum.one(runtime);
}

p += cl;
op += ocl;
return RubyFixnum.zero(runtime);
}
if (end - p == oend - op) return RubyFixnum.zero(runtime);
return end - p > oend - op ? RubyFixnum.one(runtime) : RubyFixnum.minus_one(runtime);
}

/** rb_str_match
44 changes: 43 additions & 1 deletion core/src/main/java/org/jruby/util/StringSupport.java
Original file line number Diff line number Diff line change
@@ -27,7 +27,6 @@

import static org.jcodings.Encoding.CHAR_INVALID;
import static org.jruby.RubyEnumerator.enumeratorize;
import static org.jruby.util.StringSupport.nth;

import org.jcodings.Encoding;
import org.jcodings.ascii.AsciiTables;
@@ -1953,6 +1952,49 @@ private static int trCode(int c, int[]trans, IntHash<Integer> hash, boolean cfla
}
}

public static int multiByteCasecmp(Encoding enc, ByteList value, ByteList otherValue) {
byte[]bytes = value.getUnsafeBytes();
int p = value.getBegin();
int end = p + value.getRealSize();

byte[]obytes = otherValue.getUnsafeBytes();
int op = otherValue.getBegin();
int oend = op + otherValue.getRealSize();

while (p < end && op < oend) {
final int c, oc;
if (enc.isAsciiCompatible()) {
c = bytes[p] & 0xff;
oc = obytes[op] & 0xff;
} else {
c = preciseCodePoint(enc, bytes, p, end);
oc = preciseCodePoint(enc, obytes, op, oend);
}

int cl, ocl;
if (enc.isAsciiCompatible() && Encoding.isAscii(c) && Encoding.isAscii(oc)) {
byte uc = AsciiTables.ToUpperCaseTable[c];
byte uoc = AsciiTables.ToUpperCaseTable[oc];
if (uc != uoc) {
return uc < uoc ? -1 : 1;
}
cl = ocl = 1;
} else {
cl = length(enc, bytes, p, end);
ocl = length(enc, obytes, op, oend);
// TODO: opt for 2 and 3 ?
int ret = caseCmp(bytes, p, obytes, op, cl < ocl ? cl : ocl);
if (ret != 0) return ret < 0 ? -1 : 1;
if (cl != ocl) return cl < ocl ? -1 : 1;
}

p += cl;
op += ocl;
}
if (end - p == oend - op) return 0;
return end - p > oend - op ? 1 : -1;
}

private static int rb_memsearch_ss(byte[] xsBytes, int xs, int m, byte[] ysBytes, int ys, int n) {
int y;

16 changes: 0 additions & 16 deletions spec/truffle/tags/core/string/casecmp_tags.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -734,6 +734,62 @@ public int byteSize(RubyString string) {

}

@CoreMethod(names = "casecmp", required = 1)
@NodeChildren({
@NodeChild(value = "string"),
@NodeChild(value = "other")
})
public abstract static class CaseCmpNode extends RubyNode {

public CaseCmpNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public CaseCmpNode(CaseCmpNode prev) {
super(prev);
}

@CreateCast("other") public RubyNode coerceOtherToString(RubyNode other) {
return ToStrNodeFactory.create(getContext(), getSourceSection(), other);
}

@Specialization(guards = "bothSingleByteOptimizable")
public Object caseCmpSingleByte(RubyString string, RubyString other) {
// Taken from org.jruby.RubyString#casecmp19.

if (StringSupport.areCompatible(string, other) == null) {
return nil();
}

return string.getByteList().caseInsensitiveCmp(other.getByteList());
}

@Specialization(guards = "!bothSingleByteOptimizable")
public Object caseCmp(RubyString string, RubyString other) {
// Taken from org.jruby.RubyString#casecmp19 and

final Encoding encoding = StringSupport.areCompatible(string, other);

if (encoding == null) {
return nil();
}

return multiByteCasecmp(encoding, string.getByteList(), other.getByteList());
}

@TruffleBoundary
private int multiByteCasecmp(Encoding enc, ByteList value, ByteList otherValue) {
return StringSupport.multiByteCasecmp(enc, value, otherValue);
}

public static boolean bothSingleByteOptimizable(RubyString string, RubyString other) {
final boolean stringSingleByteOptimizable = StringSupport.isSingleByteOptimizable(string, string.getByteList().getEncoding());
final boolean otherSingleByteOptimizable = StringSupport.isSingleByteOptimizable(other, other.getByteList().getEncoding());

return stringSingleByteOptimizable && otherSingleByteOptimizable;
}
}

@CoreMethod(names = "chop!", raiseIfFrozenSelf = true)
public abstract static class ChopBangNode extends CoreMethodNode {