Skip to content

Commit

Permalink
Merge pull request #723 from jruby/copy_stream_read_write
Browse files Browse the repository at this point in the history
IO.copy_stream should handle objects that respond to read or write. Fixes #437
  • Loading branch information
atambo committed May 17, 2013
2 parents 81fd721 + efe615a commit 55c9e6e
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 2 deletions.
2 changes: 0 additions & 2 deletions spec/tags/1.9/ruby/core/io/copy_stream_tags.txt
Expand Up @@ -7,5 +7,3 @@ fails:IO.copy_stream from a pipe IO to an IO starts writing at the destination I
fails:IO.copy_stream from a pipe IO to an IO leaves the destination IO position at the last write
fails:IO.copy_stream from a pipe IO to an IO copies only length bytes when specified
fails:IO.copy_stream with non-IO Objects calls #readpartial on the source Object if defined
fails:IO.copy_stream with non-IO Objects calls #read on the source Object
fails:IO.copy_stream with non-IO Objects calls #write on the destination Object
23 changes: 23 additions & 0 deletions src/org/jruby/RubyIO.java
Expand Up @@ -4256,6 +4256,8 @@ public static IRubyObject copy_stream(ThreadContext context, IRubyObject recv,
RubyIO io1 = null;
RubyIO io2 = null;

RubyString read = null;

if (args.length >= 3) {
length = args[2].convertToInteger();
if (args.length == 4) {
Expand All @@ -4271,6 +4273,12 @@ public static IRubyObject copy_stream(ThreadContext context, IRubyObject recv,
} else if (arg1.respondsTo("to_path")) {
RubyString path = (RubyString) TypeConverter.convertToType19(arg1, runtime.getString(), "to_path");
io1 = (RubyIO) RubyFile.open(context, runtime.getFile(), new IRubyObject[] {path}, Block.NULL_BLOCK);
} else if (arg1.respondsTo("read")) {
if (length == null) {
read = arg1.callMethod(context, "read", runtime.getNil()).convertToString();
} else {
read = arg1.callMethod(context, "read", length).convertToString();
}
} else {
throw runtime.newArgumentError("Should be String or IO");
}
Expand All @@ -4282,10 +4290,25 @@ public static IRubyObject copy_stream(ThreadContext context, IRubyObject recv,
} else if (arg2.respondsTo("to_path")) {
RubyString path = (RubyString) TypeConverter.convertToType19(arg2, runtime.getString(), "to_path");
io2 = (RubyIO) RubyFile.open(context, runtime.getFile(), new IRubyObject[] {path, runtime.newString("w")}, Block.NULL_BLOCK);
} else if (arg2.respondsTo("write")) {
if (read == null) {
if (length == null) {
read = io1.read(context, runtime.getNil()).convertToString();
} else {
read = io1.read(context, length).convertToString();
}
}
return arg2.callMethod(context, "write", read);
} else {
throw runtime.newArgumentError("Should be String or IO");
}

if (io1 == null) {
IRubyObject size = io2.write(context, read);
io2.flush();
return size;
}

if (!io1.openFile.isReadable()) throw runtime.newIOError("from IO is not readable");
if (!io2.openFile.isWritable()) throw runtime.newIOError("to IO is not writable");

Expand Down

0 comments on commit 55c9e6e

Please sign in to comment.