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

Commits on Aug 28, 2017

  1. Copy the full SHA
    55c26a7 View commit details
  2. [ji] make RubyIOs Java Closeable/Flushable + to_java to return stream

    ... also some minor improvements -> avoid converting to Java string
    kares committed Aug 28, 2017
    Copy the full SHA
    67adda7 View commit details
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyArgsFile.java
Original file line number Diff line number Diff line change
@@ -506,7 +506,7 @@ public static IRubyObject skip(IRubyObject recv) {

public static void argf_close(ThreadContext context, IRubyObject file) {
if(file instanceof RubyIO) {
((RubyIO)file).rbIoClose(context.runtime);
((RubyIO) file).rbIoClose(context);
} else {
file.callMethod(context, "close");
}
6 changes: 3 additions & 3 deletions core/src/main/java/org/jruby/RubyFile.java
Original file line number Diff line number Diff line change
@@ -286,16 +286,16 @@ public RubyFile(Ruby runtime, String path, FileChannel channel) {
}

@Override
protected IRubyObject rbIoClose(Ruby runtime) {
protected IRubyObject rbIoClose(ThreadContext context) {
// Make sure any existing lock is released before we try and close the file
if (openFile.currentLock != null) {
try {
openFile.currentLock.release();
} catch (IOException e) {
throw getRuntime().newIOError(e.getMessage());
throw context.runtime.newIOError(e.getMessage());
}
}
return super.rbIoClose(runtime);
return super.rbIoClose(context);
}

@JRubyMethod(required = 1)
132 changes: 76 additions & 56 deletions core/src/main/java/org/jruby/RubyIO.java
Original file line number Diff line number Diff line change
@@ -58,6 +58,8 @@
import org.jruby.util.io.PosixShim;
import jnr.constants.platform.Fcntl;

import java.io.Closeable;
import java.io.Flushable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -111,9 +113,8 @@
* @author jpetersen
*/
@JRubyClass(name="IO", include="Enumerable")
public class RubyIO extends RubyObject implements IOEncodable {
// We use a highly uncommon string to represent the paragraph delimiter (100% soln not worth it)
public static final ByteList PARAGRAPH_DELIMETER = ByteList.create("PARAGRPH_DELIM_MRK_ER");
public class RubyIO extends RubyObject implements IOEncodable, Closeable, Flushable {

public static final ByteList PARAGRAPH_SEPARATOR = ByteList.create("\n\n");
public static final String CLOSED_STREAM_MSG = "closed stream";

@@ -565,22 +566,23 @@ private void setBinmode() {
// MRI: rb_io_reopen
@JRubyMethod(name = "reopen", required = 1, optional = 1)
public IRubyObject reopen(ThreadContext context, IRubyObject[] args) {
Ruby runtime = context.runtime;
final Ruby runtime = context.runtime;
final IRubyObject nil = context.nil;
RubyIO file = this;
IRubyObject fname = context.nil, nmode = context.nil, opt = context.nil;
IRubyObject fname = nil, nmode = nil, opt = nil;
int[] oflags_p = {0};
OpenFile fptr;

switch (args.length) {
case 3:
opt = TypeConverter.checkHashType(runtime, args[2]);
if (opt.isNil()) throw getRuntime().newArgumentError(3, 2);
if (opt == nil) throw getRuntime().newArgumentError(3, 2);
case 2:
if (opt.isNil()) {
if (opt == nil) {
opt = TypeConverter.checkHashType(runtime, args[1]);
if (opt.isNil()) {
if (opt == nil) {
nmode = args[1];
opt = context.nil;
opt = nil;
}
} else {
nmode = args[1];
@@ -590,8 +592,8 @@ public IRubyObject reopen(ThreadContext context, IRubyObject[] args) {
}
if (args.length == 1) {
IRubyObject tmp = TypeConverter.ioCheckIO(runtime, fname);
if (!tmp.isNil()) {
return file.reopenIO(context, (RubyIO)tmp);
if (tmp != nil) {
return file.reopenIO(context, (RubyIO) tmp);
}
}

@@ -605,7 +607,7 @@ public IRubyObject reopen(ThreadContext context, IRubyObject[] args) {

boolean locked = fptr.lock();
try {
if (!nmode.isNil() || !opt.isNil()) {
if (nmode != nil || opt != nil) {
ConvConfig convconfig = new ConvConfig();
Object vmode_vperm = vmodeVperm(nmode, null);
int[] fmode_p = {0};
@@ -1097,20 +1099,20 @@ public IRubyObject set_encoding(ThreadContext context, IRubyObject encodingStrin

// mri: io_encoding_set
public void setEncoding(ThreadContext context, IRubyObject v1, IRubyObject v2, IRubyObject opt) {
final IRubyObject nil = context.nil;
IOEncodable.ConvConfig holder = new IOEncodable.ConvConfig();
int ecflags = openFile.encs.ecflags;
IRubyObject[] ecopts_p = {context.nil};
IRubyObject tmp;
IRubyObject[] ecopts_p = { nil };

if (!v2.isNil()) {
if (v2 != nil) {
holder.enc2 = EncodingUtils.rbToEncoding(context, v1);
tmp = v2.checkStringType();
IRubyObject tmp = v2.checkStringType();

if (!tmp.isNil()) {
RubyString internalAsString = (RubyString)tmp;
if (tmp != nil) {
RubyString internalAsString = (RubyString) tmp;

// No encoding '-'
if (internalAsString.size() == 1 && internalAsString.asJavaString().equals("-")) {
if (isDash(internalAsString)) {
/* Special case - "-" => no transcoding */
holder.enc = holder.enc2;
holder.enc2 = null;
@@ -1138,8 +1140,8 @@ public void setEncoding(ThreadContext context, IRubyObject v1, IRubyObject v2, I
EncodingUtils.SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(holder.getEnc2(), ecflags);
ecopts_p[0] = context.nil;
} else {
tmp = v1.checkStringType();
if (!tmp.isNil() && EncodingUtils.encAsciicompat(EncodingUtils.encGet(context, tmp))) {
IRubyObject tmp = v1.checkStringType();
if (tmp != nil && EncodingUtils.encAsciicompat(EncodingUtils.encGet(context, tmp))) {
EncodingUtils.parseModeEncoding(context, holder, tmp.asJavaString(), null);
EncodingUtils.SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(holder.getEnc2(), ecflags);
ecflags = EncodingUtils.econvPrepareOptions(context, opt, ecopts_p, ecflags);
@@ -1151,7 +1153,7 @@ public void setEncoding(ThreadContext context, IRubyObject v1, IRubyObject v2, I
// enc, enc2 should be set by now
}

int[] fmode_p = {openFile.getMode()};
int[] fmode_p = { openFile.getMode() };
EncodingUtils.validateEncodingBinmode(context, fmode_p, ecflags, holder);
openFile.setMode(fmode_p[0]);

@@ -1173,30 +1175,34 @@ public static IRubyObject open(ThreadContext context, IRubyObject recv, IRubyObj

public static IRubyObject ensureYieldClose(ThreadContext context, IRubyObject port, Block block) {
if (block.isGiven()) {
Ruby runtime = context.runtime;
try {
return block.yield(context, port);
} finally {
ioClose(runtime, port);
ioClose(context, port);
}
}
return port;
}

@Deprecated
public static IRubyObject sysopen(IRubyObject recv, IRubyObject[] args, Block block) {
return sysopen19(recv.getRuntime().getCurrentContext(), recv, args, block);
return sysopen(recv.getRuntime().getCurrentContext(), recv, args, block);
}

@Deprecated
public static IRubyObject sysopen19(ThreadContext context, IRubyObject recv, IRubyObject[] argv, Block block) {
return sysopen(context, recv, argv, block);
}

// rb_io_s_sysopen
@JRubyMethod(name = "sysopen", required = 1, optional = 2, meta = true)
public static IRubyObject sysopen19(ThreadContext context, IRubyObject recv, IRubyObject[] argv, Block block) {
public static IRubyObject sysopen(ThreadContext context, IRubyObject recv, IRubyObject[] argv, Block block) {
Ruby runtime = context.runtime;
IRubyObject fname, vmode, vperm;
fname = vmode = vperm = context.nil;
IRubyObject intmode;
int oflags;
ChannelFD fd;
int perm;

switch (argv.length) {
case 3:
@@ -1216,8 +1222,7 @@ else if (!(intmode = TypeConverter.checkIntegerType(context, vmode)).isNil())
vmode = vmode.convertToString();
oflags = OpenFile.ioModestrOflags(runtime, vmode.toString());
}
if (vperm.isNil()) perm = 0666;
else perm = RubyNumeric.num2int(vperm);
int perm = (vperm.isNil()) ? 0666 : RubyNumeric.num2int(vperm);

StringSupport.checkStringSafety(context.runtime, fname);
fname = ((RubyString)fname).dupFrozen();
@@ -1990,20 +1995,19 @@ public boolean isClosed() {
* MRI: rb_io_close_m
*/
@JRubyMethod
public IRubyObject close() {
Ruby runtime = getRuntime();
if (isClosed()) {
return runtime.getNil();
}
return rbIoClose(runtime);
public IRubyObject close(final ThreadContext context) {
if (isClosed()) return context.nil;
return rbIoClose(context);
}

public final void close() { close(getRuntime().getCurrentContext()); }

// io_close
protected static IRubyObject ioClose(Ruby runtime, IRubyObject io) {
ThreadContext context = runtime.getCurrentContext();
protected static IRubyObject ioClose(ThreadContext context, IRubyObject io) {
IOSites sites = sites(context);
IRubyObject closed = io.checkCallMethod(context, sites.closed_checked);
if (closed != null && closed.isTrue()) return io;
final Ruby runtime = context.runtime;
IRubyObject oldExc = runtime.getGlobalVariables().get("$!"); // Save $!
try {
closed = io.checkCallMethod(context, sites.close_checked);
@@ -2020,8 +2024,7 @@ protected static IRubyObject ioClose(Ruby runtime, IRubyObject io) {
}

// rb_io_close
protected IRubyObject rbIoClose(Ruby runtime) {
ThreadContext context = runtime.getCurrentContext();
protected IRubyObject rbIoClose(ThreadContext context) {
OpenFile fptr;
RubyIO write_io;
OpenFile write_fptr;
@@ -2033,7 +2036,7 @@ protected IRubyObject rbIoClose(Ruby runtime) {
boolean locked = write_fptr.lock();
try {
if (write_fptr != null && write_fptr.fd() != null) {
write_fptr.cleanup(runtime, true);
write_fptr.cleanup(context.runtime, true);
}
} finally {
if (locked) write_fptr.unlock();
@@ -2044,8 +2047,9 @@ protected IRubyObject rbIoClose(Ruby runtime) {

boolean locked = fptr.lock();
try {
if (fptr == null) return runtime.getNil();
if (fptr.fd() == null) return runtime.getNil();
if (fptr == null) return context.nil;
if (fptr.fd() == null) return context.nil;
final Ruby runtime = context.runtime;

// interrupt waiting threads
fptr.interruptBlockingThreads(context);
@@ -2075,7 +2079,7 @@ protected IRubyObject rbIoClose(Ruby runtime) {
if (locked) fptr.unlock();
}

return runtime.getNil();
return context.nil;
}

// MRI: rb_io_close_write
@@ -2098,8 +2102,7 @@ public IRubyObject close_write(ThreadContext context) {
throw runtime.newErrnoFromErrno(Helpers.errnoFromException(ioe), fptr.getPath());
}
fptr.setMode(fptr.getMode() & ~OpenFile.WRITABLE);
if (!fptr.isReadable())
return write_io.rbIoClose(runtime);
if (!fptr.isReadable()) return write_io.rbIoClose(context);
return context.nil;
}

@@ -2122,7 +2125,7 @@ public IRubyObject close_write(ThreadContext context) {
}
}

write_io.rbIoClose(runtime);
write_io.rbIoClose(context);
return context.nil;
}

@@ -2144,8 +2147,7 @@ public IRubyObject close_read(ThreadContext context) {
throw runtime.newErrnoFromErrno(Helpers.errnoFromException(ioe), fptr.getPath());
}
fptr.setMode(fptr.getMode() & ~OpenFile.READABLE);
if (!fptr.isWritable())
return rbIoClose(runtime);
if (!fptr.isWritable()) return rbIoClose(context);
return context.nil;
}

@@ -2179,7 +2181,7 @@ public IRubyObject close_read(ThreadContext context) {
if (locked) fptr.unlock();
}

return rbIoClose(runtime);
return rbIoClose(context);
}

@JRubyMethod(name = "close_on_exec=", notImplemented = true)
@@ -2205,6 +2207,8 @@ public RubyIO flush(ThreadContext context) {
return flushRaw(context, true);
}

public void flush() { flush(getRuntime().getCurrentContext()); }

// rb_io_flush_raw
protected RubyIO flushRaw(ThreadContext context, boolean sync) {
OpenFile fptr;
@@ -3716,7 +3720,7 @@ public static IRubyObject ioStaticWrite(ThreadContext context, IRubyObject recv,
try {
return io.write(context, string, false);
}
finally { ioClose(runtime, io); }
finally { ioClose(context, io); }
}

static IRubyObject seekBeforeAccess(ThreadContext context, RubyIO io, IRubyObject offset, int mode) {
@@ -3920,7 +3924,7 @@ public static IRubyObject popen(ThreadContext context, IRubyObject recv, IRubyOb

RubyPOpen pOpen = new RubyPOpen(runtime, args);

if ("-".equals(pOpen.cmd.toString())) {
if (isDash(pOpen.cmd)) {
throw runtime.newNotImplementedError("popen(\"-\") is unimplemented");
}

@@ -4079,16 +4083,16 @@ public static IRubyObject ensureYieldClosePipes(ThreadContext context, IRubyObje
try {
return block.yield(context, obj);
} finally {
pipePairClose(context.runtime, r, w);
pipePairClose(context, r, w);
}
}

// MRI: pipe_pair_close
private static void pipePairClose(Ruby runtime, RubyIO r, RubyIO w) {
private static void pipePairClose(ThreadContext context, RubyIO r, RubyIO w) {
try {
ioClose(runtime, r);
ioClose(context, r);
} finally {
ioClose(runtime, w);
ioClose(context, w);
}
}

@@ -4672,6 +4676,18 @@ public boolean getBOM() {
return openFile.isBOM();
}

@Override
public Object toJava(Class target) {
if (target == java.io.InputStream.class) {
getOpenFile().checkReadable(getRuntime().getCurrentContext());
return getInStream();
}
if (target == java.io.OutputStream.class) {
getOpenFile().checkWritable(getRuntime().getCurrentContext());
return getOutStream();
}
return super.toJava(target);
}

// MRI: rb_io_ascii8bit_binmode
protected RubyIO setAscii8bitBinmode() {
@@ -4683,10 +4699,14 @@ protected RubyIO setAscii8bitBinmode() {
return this;
}

private static boolean isDash(RubyString str) {
return str.size() == 1 && str.getByteList().get(0) == '-'; // "-".equals(str.toString());
}

public final OpenFile MakeOpenFile() {
Ruby runtime = getRuntime();
if (openFile != null) {
rbIoClose(runtime);
rbIoClose(runtime.getCurrentContext());
rb_io_fptr_finalize(runtime, openFile);
openFile = null;
}
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyKernel.java
Original file line number Diff line number Diff line change
@@ -1460,7 +1460,7 @@ public static IRubyObject backquote(ThreadContext context, IRubyObject recv, IRu

fptr = ((RubyIO)port).getOpenFileChecked();
result = fptr.readAll(context, fptr.remainSize(), context.nil);
((RubyIO)port).rbIoClose(runtime);
((RubyIO)port).rbIoClose(context);

return result;
}
Loading