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

Commits on Mar 12, 2015

  1. Copy the full SHA
    e66f08e View commit details
  2. Copy the full SHA
    74861eb View commit details
  3. Copy the full SHA
    763bd8e View commit details
  4. Copy the full SHA
    d00be24 View commit details
  5. Copy the full SHA
    f6b0705 View commit details
51 changes: 11 additions & 40 deletions core/src/main/java/org/jruby/RubyString.java
Original file line number Diff line number Diff line change
@@ -206,7 +206,8 @@ public final void clearCodeRange() {
flags &= ~CR_MASK;
}

private void keepCodeRange() {
@Override
public final void keepCodeRange() {
if (getCodeRange() == CR_BROKEN) clearCodeRange();
}

@@ -4608,7 +4609,12 @@ public IRubyObject delete_bang19(ThreadContext context, IRubyObject arg) {
Encoding enc = checkEncoding(otherStr);
final boolean[]squeeze = new boolean[StringSupport.TRANS_SIZE + 1];
StringSupport.TrTables tables = StringSupport.trSetupTable(otherStr.value, runtime, squeeze, null, true, enc);
return delete_bangCommon19(runtime, squeeze, tables, enc);

if (StringSupport.delete_bangCommon19(this, runtime, squeeze, tables, enc) == null) {
return runtime.getNil();
}

return this;
}

@JRubyMethod(name = "delete!", required = 1, rest = true)
@@ -4626,46 +4632,11 @@ public IRubyObject delete_bang19(ThreadContext context, IRubyObject[] args) {
tables = StringSupport.trSetupTable(otherStr.value, runtime, squeeze, tables, false, enc);
}

return delete_bangCommon19(runtime, squeeze, tables, enc);
}

private IRubyObject delete_bangCommon19(Ruby runtime, boolean[]squeeze, StringSupport.TrTables tables, Encoding enc) {
modifyAndKeepCodeRange();

int s = value.getBegin();
int t = s;
int send = s + value.getRealSize();
byte[]bytes = value.getUnsafeBytes();
boolean modify = false;
boolean asciiCompatible = enc.isAsciiCompatible();
int cr = asciiCompatible ? CR_7BIT : CR_VALID;
while (s < send) {
int c;
if (asciiCompatible && Encoding.isAscii(c = bytes[s] & 0xff)) {
if (squeeze[c]) {
modify = true;
} else {
if (t != s) bytes[t] = (byte)c;
t++;
}
s++;
} else {
c = codePoint(runtime, enc, bytes, s, send);
int cl = codeLength(runtime, enc, c);
if (StringSupport.trFind(c, squeeze, tables)) {
modify = true;
} else {
if (t != s) enc.codeToMbc(c, bytes, t);
t += cl;
if (cr == CR_7BIT) cr = CR_VALID;
}
s += cl;
}
if (StringSupport.delete_bangCommon19(this, runtime, squeeze, tables, enc) == null) {
return runtime.getNil();
}
value.setRealSize(t - value.getBegin());
setCodeRange(cr);

return modify ? this : runtime.getNil();
return this;
}

/** rb_str_squeeze / rb_str_squeeze_bang
1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/util/CodeRangeable.java
Original file line number Diff line number Diff line change
@@ -32,4 +32,5 @@ public interface CodeRangeable extends ByteListHolder {
public boolean isCodeRangeValid();
public void setCodeRange(int codeRange);
public void clearCodeRange();
public void keepCodeRange();
}
45 changes: 45 additions & 0 deletions core/src/main/java/org/jruby/util/StringSupport.java
Original file line number Diff line number Diff line change
@@ -1279,4 +1279,49 @@ public static void replaceInternal19(int beg, int len, CodeRangeable source, Cod
public static boolean isAsciiOnly(CodeRangeable string) {
return string.getByteList().getEncoding().isAsciiCompatible() && string.scanForCodeRange() == CR_7BIT;
}

/**
* rb_str_delete_bang
*/
public static CodeRangeable delete_bangCommon19(CodeRangeable rubyString, Ruby runtime, boolean[] squeeze, TrTables tables, Encoding enc) {
rubyString.modify();
rubyString.keepCodeRange();

final ByteList value = rubyString.getByteList();

int s = value.getBegin();
int t = s;
int send = s + value.getRealSize();
byte[]bytes = value.getUnsafeBytes();
boolean modify = false;
boolean asciiCompatible = enc.isAsciiCompatible();
int cr = asciiCompatible ? CR_7BIT : CR_VALID;
while (s < send) {
int c;
if (asciiCompatible && Encoding.isAscii(c = bytes[s] & 0xff)) {
if (squeeze[c]) {
modify = true;
} else {
if (t != s) bytes[t] = (byte)c;
t++;
}
s++;
} else {
c = codePoint(runtime, enc, bytes, s, send);
int cl = codeLength(runtime, enc, c);
if (trFind(c, squeeze, tables)) {
modify = true;
} else {
if (t != s) enc.codeToMbc(c, bytes, t);
t += cl;
if (cr == CR_7BIT) cr = CR_VALID;
}
s += cl;
}
}
value.setRealSize(t - value.getBegin());
rubyString.setCodeRange(cr);

return modify ? rubyString : null;
}
}
12 changes: 0 additions & 12 deletions spec/truffle/tags/core/string/delete_tags.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,2 @@
fails:String#delete returns a new string with the chars from the intersection of sets removed
fails:String#delete raises an ArgumentError when given no arguments
fails:String#delete negates sets starting with ^
fails:String#delete deletes all chars in a sequence
fails:String#delete deletes multibyte characters
fails:String#delete respects backslash for escaping a -
fails:String#delete raises if the given ranges are invalid
fails:String#delete taints result when self is tainted
fails:String#delete tries to convert each set arg to a string using to_str
fails:String#delete raises a TypeError when one set arg can't be converted to a string
fails:String#delete returns subclass instances when called on a subclass
fails:String#delete! modifies self in place and returns self
fails:String#delete! returns nil if no modifications were made
fails:String#delete! raises a RuntimeError when self is frozen
Original file line number Diff line number Diff line change
@@ -701,6 +701,7 @@ public int count(VirtualFrame frame, RubyString string, Object[] otherStrings) {
notDesignedForCompilation();

if (otherStrings.length == 0) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().argumentErrorEmptyVarargs(this));
}

@@ -736,6 +737,64 @@ public RubiniusByteArray data(RubyString string) {
}
}

@CoreMethod(names = "delete!", argumentsAsArray = true, raiseIfFrozenSelf = true)
public abstract static class DeleteBangNode extends CoreMethodNode {

@Child private ToStrNode toStr;

public DeleteBangNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
toStr = ToStrNodeFactory.create(context, sourceSection, null);
}

public DeleteBangNode(DeleteBangNode prev) {
super(prev);
toStr = prev.toStr;
}

@Specialization
public Object deleteBang(VirtualFrame frame, RubyString string, Object[] otherStrings) {
if (string.getBytes().length() == 0) {
return getContext().getCoreLibrary().getNilObject();
}

if (otherStrings.length == 0) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().argumentErrorEmptyVarargs(this));
}

return deleteBangSlow(frame, string, otherStrings);
}

@CompilerDirectives.TruffleBoundary
private Object deleteBangSlow(VirtualFrame frame, RubyString string, Object[] args) {
RubyString[] otherStrings = new RubyString[args.length];

for (int i = 0; i < args.length; i++) {
otherStrings[i] = toStr.executeRubyString(frame, args[i]);
}

RubyString otherString = otherStrings[0];
Encoding enc = string.checkEncoding(otherString);

boolean[] squeeze = new boolean[StringSupport.TRANS_SIZE + 1];
StringSupport.TrTables tables = StringSupport.trSetupTable(otherString.getBytes(),
getContext().getRuntime(),
squeeze, null, true, enc);

for (int i = 1; i < otherStrings.length; i++) {
enc = string.checkEncoding(otherStrings[i]);
tables = StringSupport.trSetupTable(otherStrings[i].getBytes(), getContext().getRuntime(), squeeze, tables, false, enc);
}

if (StringSupport.delete_bangCommon19(string, getContext().getRuntime(), squeeze, tables, enc) == null) {
return getContext().getCoreLibrary().getNilObject();
}

return string;
}
}

@CoreMethod(names = "downcase", taintFromSelf = true)
public abstract static class DowncaseNode extends CoreMethodNode {

Original file line number Diff line number Diff line change
@@ -184,6 +184,13 @@ public final void clearCodeRange() {
codeRange = StringSupport.CR_UNKNOWN;
}

@Override
public final void keepCodeRange() {
if (getCodeRange() == StringSupport.CR_BROKEN) {
clearCodeRange();
}
}

@Override
public final void modify() {
// TODO (nirvdrum 16-Feb-15): This should check whether the underlying ByteList is being shared and copy if necessary.
Original file line number Diff line number Diff line change
@@ -121,6 +121,13 @@ public final void clearCodeRange() {
codeRange = StringSupport.CR_UNKNOWN;
}

@Override
public final void keepCodeRange() {
if (getCodeRange() == StringSupport.CR_BROKEN) {
clearCodeRange();
}
}

@Override
public final void modify() {
throw new UnsupportedOperationException();
5 changes: 5 additions & 0 deletions truffle/src/main/ruby/core/rubinius/common/string.rb
Original file line number Diff line number Diff line change
@@ -67,6 +67,11 @@ def chomp(separator=$/)
str.chomp!(separator) || str
end

def delete(*strings)
str = dup
str.delete!(*strings) || str
end

def slice!(one, two=undefined)
Rubinius.check_frozen
# This is un-DRY, but it's a simple manual argument splitting. Keeps