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

Commits on Jan 16, 2015

  1. 2
    Copy the full SHA
    752dd26 View commit details
  2. Copy the full SHA
    6ea1701 View commit details
38 changes: 38 additions & 0 deletions core/src/main/java/org/jruby/RubyEncoding.java
Original file line number Diff line number Diff line change
@@ -50,6 +50,7 @@
import org.jruby.runtime.encoding.EncodingService;
import org.jruby.runtime.opto.OptoFactory;
import org.jruby.util.ByteList;
import org.jruby.util.CodeRangeable;
import org.jruby.util.StringSupport;
import org.jruby.util.io.EncodingUtils;
import org.jruby.util.unsafe.UnsafeHolder;
@@ -165,6 +166,43 @@ public static Encoding areCompatible(IRubyObject obj1, IRubyObject obj2) {
return null;
}

public static Encoding areCompatible(CodeRangeable obj1, CodeRangeable obj2) {
Encoding enc1 = obj1.getByteList().getEncoding();
Encoding enc2 = obj2.getByteList().getEncoding();

if (enc1 == null || enc2 == null) return null;
if (enc1 == enc2) return enc1;

if (obj2.getByteList().getRealSize() == 0) return enc1;
if (obj1.getByteList().getRealSize() == 0) {
return enc1.isAsciiCompatible() && obj2 instanceof RubyString &&
((RubyString) obj2).isAsciiOnly() ? enc1 : enc2;
}

if (!enc1.isAsciiCompatible() || !enc2.isAsciiCompatible()) return null;

int cr1 = obj1.scanForCodeRange();
if (obj2 instanceof RubyString) {
int cr2 = obj2.scanForCodeRange();
return areCompatible(enc1, cr1, enc2, cr2);
}
if (cr1 == StringSupport.CR_7BIT) return enc2;

return null;
}

public static Encoding areCompatible(Encoding enc1, Encoding enc2) {
if (enc1 == null || enc2 == null) return null;
if (enc1 == enc2) return enc1;

if (!enc1.isAsciiCompatible() || !enc2.isAsciiCompatible()) return null;

if (enc2 instanceof USASCIIEncoding) return enc1;
if (enc1 instanceof USASCIIEncoding) return enc2;

return null;
}

// last block in rb_enc_compatible
public static Encoding areCompatible(Encoding enc1, int cr1, Encoding enc2, int cr2) {
if (cr1 != cr2) {
41 changes: 41 additions & 0 deletions core/src/main/java/org/jruby/truffle/nodes/core/EncodingNodes.java
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;
import org.jcodings.Encoding;
import org.jcodings.EncodingDB;
import org.jcodings.specific.ASCIIEncoding;
@@ -29,6 +30,46 @@
@CoreClass(name = "Encoding")
public abstract class EncodingNodes {

@CoreMethod(names = "compatible?", needsSelf = false, onSingleton = true, required = 2)
public abstract static class CompatibleQueryNode extends CoreMethodNode {

ConditionProfile compatibleEncodingProfile = ConditionProfile.createBinaryProfile();

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

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

@Specialization
public Object isCompatible(RubyString first, RubyString second) {
notDesignedForCompilation();

Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(first, second);

if (compatibleEncodingProfile.profile(compatibleEncoding != null)) {
return RubyEncoding.getEncoding(compatibleEncoding);
} else {
return getContext().getCoreLibrary().getNilObject();
}
}

@Specialization
public Object isCompatible(RubyEncoding first, RubyEncoding second) {
notDesignedForCompilation();

Encoding compatibleEncoding = org.jruby.RubyEncoding.areCompatible(first.getEncoding(), second.getEncoding());

if (compatibleEncodingProfile.profile(compatibleEncoding != null)) {
return RubyEncoding.getEncoding(compatibleEncoding);
} else {
return getContext().getCoreLibrary().getNilObject();
}
}
}

@CoreMethod(names = "default_external", onSingleton = true)
public abstract static class DefaultExternalNode extends CoreMethodNode {

Original file line number Diff line number Diff line change
@@ -34,6 +34,57 @@ class Regexp
FIXEDENCODING = 16
NOENCODING = 32

def self.convert(pattern)
return pattern if pattern.kind_of? Regexp
if pattern.kind_of? Array
return union(*pattern)
else
return Regexp.quote(pattern.to_s)
end
end

def self.compatible?(*patterns)
encodings = patterns.map{ |r| convert(r).encoding }
last_enc = encodings.pop
encodings.each do |encoding|
raise ArgumentError, "incompatible encodings: #{encoding} and #{last_enc}" unless Encoding.compatible?(last_enc, encoding)
last_enc = encoding
end
end

def self.union(*patterns)
case patterns.size
when 0
return %r/(?!)/
when 1
pat = patterns.first
case pat
when Array
return union(*pat)
when Regexp
return pat
else
return Regexp.new(Regexp.quote(StringValue(pat)))
end
else
compatible?(*patterns)
enc = convert(patterns.first).encoding
end

str = "".encode(enc)
sep = "|".encode(enc)
patterns.each_with_index do |pat, idx|
str << sep if idx != 0
if pat.kind_of? Regexp
str << pat.to_s
else
str << Regexp.quote(StringValue(pat))
end
end

Regexp.new(str)
end

end

class MatchData
15 changes: 0 additions & 15 deletions spec/truffle/tags/core/encoding/compatible_tags.txt
Original file line number Diff line number Diff line change
@@ -1,24 +1,13 @@
fails:Encoding.compatible? String, String when the first's Encoding is valid US-ASCII returns US-ASCII when the second's is US-ASCII
fails:Encoding.compatible? String, String when the first's Encoding is valid US-ASCII returns US-ASCII if the second String is ASCII-8BIT and ASCII only
fails:Encoding.compatible? String, String when the first's Encoding is valid US-ASCII returns ASCII-8BIT if the second String is ASCII-8BIT but not ASCII only
fails:Encoding.compatible? String, String when the first's Encoding is valid US-ASCII returns US-ASCII if the second String is UTF-8 and ASCII only
fails:Encoding.compatible? String, String when the first's Encoding is valid US-ASCII returns UTF-8 if the second String is UTF-8 but not ASCII only
fails:Encoding.compatible? String, String when the first's Encoding is ASCII compatible and ASCII only returns the first's Encoding if the second is ASCII compatible and ASCII only
fails:Encoding.compatible? String, String when the first's Encoding is ASCII compatible and ASCII only returns the second's Encoding if the second is ASCII compatible but not ASCII only
fails:Encoding.compatible? String, String when the first's Encoding is ASCII compatible and ASCII only returns nil if the second's Encoding is not ASCII compatible
fails:Encoding.compatible? String, String when the first's Encoding is ASCII compatible but not ASCII only returns the first's Encoding if the second's is valid US-ASCII
fails:Encoding.compatible? String, String when the first's Encoding is ASCII compatible but not ASCII only returns the first's Encoding if the second's is UTF-8 and ASCII only
fails:Encoding.compatible? String, String when the first's Encoding is ASCII compatible but not ASCII only returns nil if the second encoding is ASCII compatible but neither String's encoding is ASCII only
fails:Encoding.compatible? String, String when the first's Encoding is not ASCII compatible returns nil when the second String is US-ASCII
fails:Encoding.compatible? String, String when the first's Encoding is not ASCII compatible returns nil when the second String is ASCII-8BIT and ASCII only
fails:Encoding.compatible? String, String when the first's Encoding is not ASCII compatible returns nil when the second String is ASCII-8BIT but not ASCII only
fails:Encoding.compatible? String, String when the first's Encoding is not ASCII compatible returns the Encoding when the second's Encoding is not ASCII compatible but the same as the first's Encoding
fails:Encoding.compatible? String, String when the first's Encoding is invalid returns the first's Encoding when the second's Encoding is US-ASCII
fails:Encoding.compatible? String, String when the first's Encoding is invalid returns the first's Encoding when the second String is ASCII only
fails:Encoding.compatible? String, String when the first's Encoding is invalid returns nil when the second's Encoding is ASCII-8BIT but not ASCII only
fails:Encoding.compatible? String, String when the first's Encoding is invalid returns nil when the second's Encoding is invalid and ASCII only
fails:Encoding.compatible? String, String when the first's Encoding is invalid returns nil when the second's Encoding is invalid and not ASCII only
fails:Encoding.compatible? String, String when the first's Encoding is invalid returns the Encoding when the second's Encoding is invalid but the same as the first
fails:Encoding.compatible? String, Regexp returns US-ASCII if both are US-ASCII
fails:Encoding.compatible? String, Regexp returns the String's Encoding if it is not US-ASCII but both are ASCII only
fails:Encoding.compatible? String, Regexp returns the String's Encoding if the String is not ASCII only
@@ -35,10 +24,6 @@ fails:Encoding.compatible? Symbol, Regexp returns US-ASCII if both are US-ASCII
fails:Encoding.compatible? Symbol, Regexp returns the Regexp's Encoding if it is not US-ASCII and not ASCII only
fails:Encoding.compatible? Symbol, Symbol returns US-ASCII if both are US-ASCII
fails:Encoding.compatible? Symbol, Symbol returns the first's Encoding if it is not ASCII only
fails:Encoding.compatible? Encoding, Encoding returns nil if one of the encodings is a dummy encoding
fails:Encoding.compatible? Encoding, Encoding returns nil if one of the encodings is not US-ASCII
fails:Encoding.compatible? Encoding, Encoding returns the first if the second is US-ASCII
fails:Encoding.compatible? Encoding, Encoding returns the Encoding if both are the same
fails:Encoding.compatible? Object, Object returns nil for Object, String
fails:Encoding.compatible? Object, Object returns nil for Object, Regexp
fails:Encoding.compatible? Object, Object returns nil for Object, Symbol
24 changes: 0 additions & 24 deletions spec/truffle/tags/core/regexp/union_tags.txt
Original file line number Diff line number Diff line change
@@ -1,26 +1,2 @@
fails:Regexp.union returns /(?!)/ when passed no arguments
fails:Regexp.union returns a regular expression that will match passed arguments
fails:Regexp.union quotes any string arguments
fails:Regexp.union returns a Regexp with the encoding of an ASCII-incompatible String argument
fails:Regexp.union returns a Regexp with the encoding of a String containing non-ASCII-compatible characters
fails:Regexp.union returns a Regexp with US-ASCII encoding if all arguments are ASCII-only
fails:Regexp.union returns a Regexp with the encoding of multiple non-conflicting ASCII-incompatible String arguments
fails:Regexp.union returns a Regexp with the encoding of multiple non-conflicting Strings containing non-ASCII-compatible characters
fails:Regexp.union returns a Regexp with the encoding of a String containing non-ASCII-compatible characters and another ASCII-only String
fails:Regexp.union returns a Regexp with UTF-8 if one part is UTF-8
fails:Regexp.union returns a Regexp if an array of string with special characters is passed
fails:Regexp.union uses to_str to convert arguments (if not Regexp)
fails:Regexp.union accepts a single array of patterns as arguments
fails:Regexp.union raises ArgumentError if the arguments include conflicting ASCII-incompatible Strings
fails:Regexp.union raises ArgumentError if the arguments include conflicting ASCII-incompatible Regexps
fails:Regexp.union raises ArgumentError if the arguments include conflicting fixed encoding Regexps
fails:Regexp.union raises ArgumentError if the arguments include a fixed encoding Regexp and a String containing non-ASCII-compatible characters in a different encoding
fails:Regexp.union raises ArgumentError if the arguments include a String containing non-ASCII-compatible characters and a fixed encoding Regexp in a different encoding
fails:Regexp.union raises ArgumentError if the arguments include an ASCII-incompatible String and an ASCII-only String
fails:Regexp.union raises ArgumentError if the arguments include an ASCII-incompatible Regexp and an ASCII-only String
fails:Regexp.union raises ArgumentError if the arguments include an ASCII-incompatible String and an ASCII-only Regexp
fails:Regexp.union raises ArgumentError if the arguments include an ASCII-incompatible Regexp and an ASCII-only Regexp
fails:Regexp.union raises ArgumentError if the arguments include an ASCII-incompatible String and a String containing non-ASCII-compatible characters in a different encoding
fails:Regexp.union raises ArgumentError if the arguments include an ASCII-incompatible Regexp and a String containing non-ASCII-compatible characters in a different encoding
fails:Regexp.union raises ArgumentError if the arguments include an ASCII-incompatible String and a Regexp containing non-ASCII-compatible characters in a different encoding
fails:Regexp.union raises ArgumentError if the arguments include an ASCII-incompatible Regexp and a Regexp containing non-ASCII-compatible characters in a different encoding