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

Commits on Dec 18, 2014

  1. Copy the full SHA
    371ba62 View commit details
  2. Copy the full SHA
    63a4d7f View commit details
  3. Copy the full SHA
    d77e59e View commit details
  4. Copy the full SHA
    6f80e75 View commit details
  5. Copy the full SHA
    ed7d1df View commit details
144 changes: 9 additions & 135 deletions core/src/main/java/org/jruby/RubyString.java
Original file line number Diff line number Diff line change
@@ -2030,138 +2030,20 @@ public IRubyObject dump() {

@JRubyMethod(name = "dump")
public IRubyObject dump19() {
return dumpCommon(true);
}
ByteList outBytes = StringSupport.dumpCommon(getRuntime(), value);

private IRubyObject dumpCommon(boolean is1_9) {
Ruby runtime = getRuntime();
ByteList buf = null;
final RubyString result = new RubyString(getRuntime(), getMetaClass(), outBytes);
Encoding enc = value.getEncoding();

int p = value.getBegin();
int end = p + value.getRealSize();
byte[]bytes = value.getUnsafeBytes();

int len = 2;
while (p < end) {
int c = bytes[p++] & 0xff;

switch (c) {
case '"':case '\\':case '\n':case '\r':case '\t':case '\f':
case '\013': case '\010': case '\007': case '\033':
len += 2;
break;
case '#':
len += isEVStr(bytes, p, end) ? 2 : 1;
break;
default:
if (ASCII.isPrint(c)) {
len++;
} else {
if (is1_9 && enc instanceof UTF8Encoding) {
int n = StringSupport.preciseLength(enc, bytes, p - 1, end) - 1;
if (n > 0) {
if (buf == null) buf = new ByteList();
int cc = codePoint(runtime, enc, bytes, p - 1, end);
Sprintf.sprintf(runtime, buf, "%x", cc);
len += buf.getRealSize() + 4;
buf.setRealSize(0);
p += n;
break;
}
}
len += 4;
}
break;
}
}

if (is1_9 && !enc.isAsciiCompatible()) {
len += ".force_encoding(\"".length() + enc.getName().length + "\")".length();
if (!enc.isAsciiCompatible()) {
result.cat(".force_encoding(\"".getBytes());
result.cat(enc.getName());
result.cat((byte)'"').cat((byte)')');
enc = ASCII;
}
result.associateEncoding(enc);
result.setCodeRange(CR_7BIT);

ByteList outBytes = new ByteList(len);
byte out[] = outBytes.getUnsafeBytes();
int q = 0;
p = value.getBegin();
end = p + value.getRealSize();

out[q++] = '"';
while (p < end) {
int c = bytes[p++] & 0xff;
if (c == '"' || c == '\\') {
out[q++] = '\\';
out[q++] = (byte)c;
} else if (c == '#') {
if (isEVStr(bytes, p, end)) out[q++] = '\\';
out[q++] = '#';
} else if (!is1_9 && ASCII.isPrint(c)) {
out[q++] = (byte)c;
} else if (c == '\n') {
out[q++] = '\\';
out[q++] = 'n';
} else if (c == '\r') {
out[q++] = '\\';
out[q++] = 'r';
} else if (c == '\t') {
out[q++] = '\\';
out[q++] = 't';
} else if (c == '\f') {
out[q++] = '\\';
out[q++] = 'f';
} else if (c == '\013') {
out[q++] = '\\';
out[q++] = 'v';
} else if (c == '\010') {
out[q++] = '\\';
out[q++] = 'b';
} else if (c == '\007') {
out[q++] = '\\';
out[q++] = 'a';
} else if (c == '\033') {
out[q++] = '\\';
out[q++] = 'e';
} else if (is1_9 && ASCII.isPrint(c)) {
out[q++] = (byte)c;
} else {
out[q++] = '\\';
if (is1_9) {
if (enc instanceof UTF8Encoding) {
int n = StringSupport.preciseLength(enc, bytes, p - 1, end) - 1;
if (n > 0) {
int cc = codePoint(runtime, enc, bytes, p - 1, end);
p += n;
outBytes.setRealSize(q);
Sprintf.sprintf(runtime, outBytes, "u{%x}", cc);
q = outBytes.getRealSize();
continue;
}
}
outBytes.setRealSize(q);
Sprintf.sprintf(runtime, outBytes, "x%02X", c);
q = outBytes.getRealSize();
} else {
outBytes.setRealSize(q);
Sprintf.sprintf(runtime, outBytes, "%03o", c);
q = outBytes.getRealSize();
}
}
}
out[q++] = '"';
outBytes.setRealSize(q);
assert out == outBytes.getUnsafeBytes(); // must not reallocate

final RubyString result = new RubyString(runtime, getMetaClass(), outBytes);
if (is1_9) {
if (!enc.isAsciiCompatible()) {
result.cat(".force_encoding(\"".getBytes());
result.cat(enc.getName());
result.cat((byte)'"').cat((byte)')');
enc = ASCII;
}
result.associateEncoding(enc);
result.setCodeRange(CR_7BIT);
}
return result.infectBy(this);
}

@@ -2206,14 +2088,6 @@ private void raiseIndexOutOfString(int index) {
throw getRuntime().newIndexError("index " + index + " out of string");
}

private boolean isEVStr(byte[]bytes, int p, int end) {
return p < end ? isEVStr(bytes[p] & 0xff) : false;
}

public boolean isEVStr(int c) {
return c == '$' || c == '@' || c == '{';
}

/** rb_str_inspect
*
*/
20 changes: 20 additions & 0 deletions core/src/main/java/org/jruby/truffle/nodes/core/StringNodes.java
Original file line number Diff line number Diff line change
@@ -708,6 +708,26 @@ public RubyString rstrip(RubyString string) {

}

@CoreMethod(names = "dump")
public abstract static class DumpNode extends CoreMethodNode {

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

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

@Specialization
public RubyString rstrip(RubyString string) {
notDesignedForCompilation();

return string.dump();
}

}

@CoreMethod(names = "scan", required = 1, needsBlock = true)
public abstract static class ScanNode extends YieldingCoreMethodNode {

Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.util.ByteList;
import org.jruby.util.StringSupport;

/**
* Represents the Ruby {@code String} class.
@@ -106,6 +107,14 @@ public static String rjust(String string, int length, String padding) {
return builder.toString();
}

public RubyString dump() {
ByteList outputBytes = StringSupport.dumpCommon(getContext().getRuntime(), bytes);

final RubyString result = getContext().makeString(outputBytes);

return result;
}

@Override
public boolean equals(Object other) {
RubyNode.notDesignedForCompilation();
130 changes: 129 additions & 1 deletion core/src/main/java/org/jruby/util/StringSupport.java
Original file line number Diff line number Diff line change
@@ -30,11 +30,11 @@
import org.jcodings.Encoding;
import org.jcodings.ascii.AsciiTables;
import org.jcodings.specific.ASCIIEncoding;
import org.jcodings.specific.UTF8Encoding;
import org.joni.Matcher;
import org.jruby.Ruby;
import org.jruby.RubyObject;
import org.jruby.RubyString;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

import sun.misc.Unsafe;
@@ -664,6 +664,10 @@ public static void TERM_FILL(byte[] ptrBytes, int ptr, int termlen) {
Arrays.fill(ptrBytes, term_fill_ptr, term_fill_len, (byte)0);
}

/**
* rb_str_scan
*/

public static int positionEndForScan(ByteList value, Matcher matcher, Encoding enc, int begin, int range) {
int end = matcher.getEnd();
if (matcher.getBegin() == end) {
@@ -676,4 +680,128 @@ public static int positionEndForScan(ByteList value, Matcher matcher, Encoding e
return end;
}
}

/**
* rb_str_dump
*/

public static ByteList dumpCommon(Ruby runtime, ByteList byteList) {
ByteList buf = null;
Encoding enc = byteList.getEncoding();

int p = byteList.getBegin();
int end = p + byteList.getRealSize();
byte[]bytes = byteList.getUnsafeBytes();

int len = 2;
while (p < end) {
int c = bytes[p++] & 0xff;

switch (c) {
case '"':case '\\':case '\n':case '\r':case '\t':case '\f':
case '\013': case '\010': case '\007': case '\033':
len += 2;
break;
case '#':
len += isEVStr(bytes, p, end) ? 2 : 1;
break;
default:
if (ASCIIEncoding.INSTANCE.isPrint(c)) {
len++;
} else {
if (enc instanceof UTF8Encoding) {
int n = preciseLength(enc, bytes, p - 1, end) - 1;
if (n > 0) {
if (buf == null) buf = new ByteList();
int cc = codePoint(runtime, enc, bytes, p - 1, end);
Sprintf.sprintf(runtime, buf, "%x", cc);
len += buf.getRealSize() + 4;
buf.setRealSize(0);
p += n;
break;
}
}
len += 4;
}
break;
}
}

if (!enc.isAsciiCompatible()) {
len += ".force_encoding(\"".length() + enc.getName().length + "\")".length();
}

ByteList outBytes = new ByteList(len);
byte out[] = outBytes.getUnsafeBytes();
int q = 0;
p = byteList.getBegin();
end = p + byteList.getRealSize();

out[q++] = '"';
while (p < end) {
int c = bytes[p++] & 0xff;
if (c == '"' || c == '\\') {
out[q++] = '\\';
out[q++] = (byte)c;
} else if (c == '#') {
if (isEVStr(bytes, p, end)) out[q++] = '\\';
out[q++] = '#';
} else if (c == '\n') {
out[q++] = '\\';
out[q++] = 'n';
} else if (c == '\r') {
out[q++] = '\\';
out[q++] = 'r';
} else if (c == '\t') {
out[q++] = '\\';
out[q++] = 't';
} else if (c == '\f') {
out[q++] = '\\';
out[q++] = 'f';
} else if (c == '\013') {
out[q++] = '\\';
out[q++] = 'v';
} else if (c == '\010') {
out[q++] = '\\';
out[q++] = 'b';
} else if (c == '\007') {
out[q++] = '\\';
out[q++] = 'a';
} else if (c == '\033') {
out[q++] = '\\';
out[q++] = 'e';
} else if (ASCIIEncoding.INSTANCE.isPrint(c)) {
out[q++] = (byte)c;
} else {
out[q++] = '\\';
if (enc instanceof UTF8Encoding) {
int n = preciseLength(enc, bytes, p - 1, end) - 1;
if (n > 0) {
int cc = codePoint(runtime, enc, bytes, p - 1, end);
p += n;
outBytes.setRealSize(q);
Sprintf.sprintf(runtime, outBytes, "u{%x}", cc);
q = outBytes.getRealSize();
continue;
}
}
outBytes.setRealSize(q);
Sprintf.sprintf(runtime, outBytes, "x%02X", c);
q = outBytes.getRealSize();
}
}
out[q++] = '"';
outBytes.setRealSize(q);
assert out == outBytes.getUnsafeBytes(); // must not reallocate

return outBytes;
}

public static boolean isEVStr(byte[]bytes, int p, int end) {
return p < end ? isEVStr(bytes[p] & 0xff) : false;
}

public static boolean isEVStr(int c) {
return c == '$' || c == '@' || c == '{';
}
}