@JRubyMethod(name = "read", optional = 2) public IRubyObject read(ThreadContext context, IRubyObject[] args) { checkReadable(); Ruby runtime = context.runtime; IRubyObject str = runtime.getNil(); int len; boolean binary = false; switch (args.length) { case 2: str = args[1]; if (!str.isNil()) { str = str.convertToString(); ((RubyString) str).modify(); } case 1: if (!args[0].isNil()) { len = RubyNumeric.fix2int(args[0]); if (len < 0) { throw getRuntime().newArgumentError("negative length " + len + " given"); } if (len > 0 && isEndOfString()) { if (!str.isNil()) ((RubyString) str).resize(0); return getRuntime().getNil(); } binary = true; break; } case 0: len = ptr.string.size(); if (len <= ptr.pos) { if (str.isNil()) { str = runtime.newString(); } else { ((RubyString) str).resize(0); } return str; } else { len -= ptr.pos; } break; default: throw getRuntime().newArgumentError(args.length, 0); } if (str.isNil()) { str = strioSubstr(runtime, ptr.pos, len); if (binary) ((RubyString) str).setEncoding(ASCIIEncoding.INSTANCE); } else { int rest = ptr.string.size() - ptr.pos; if (len > rest) len = rest; ((RubyString) str).resize(len); ByteList strByteList = ((RubyString) str).getByteList(); byte[] strBytes = strByteList.getUnsafeBytes(); ByteList dataByteList = ptr.string.getByteList(); byte[] dataBytes = dataByteList.getUnsafeBytes(); System.arraycopy( dataBytes, dataByteList.getBegin() + ptr.pos, strBytes, strByteList.getBegin(), len); if (binary) { ((RubyString) str).setEncoding(ASCIIEncoding.INSTANCE); } else { ((RubyString) str).setEncoding(ptr.string.getEncoding()); } } ptr.pos += ((RubyString) str).size(); return str; }
@SuppressWarnings("fallthrough") @JRubyMethod(name = "read", optional = 2) @Override public IRubyObject read(IRubyObject[] args) { checkReadable(); ByteList buf = null; int length = 0; int oldLength = 0; RubyString originalString = null; switch (args.length) { case 2: originalString = args[1].convertToString(); // must let original string know we're modifying, so shared buffers aren't damaged originalString.modify(); buf = originalString.getByteList(); case 1: if (!args[0].isNil()) { length = RubyNumeric.fix2int(args[0]); oldLength = length; if (length < 0) { throw getRuntime().newArgumentError("negative length " + length + " given"); } if (length > 0 && isEndOfString()) { data.eof = true; if (buf != null) buf.setRealSize(0); return getRuntime().getNil(); } else if (data.eof) { if (buf != null) buf.setRealSize(0); return getRuntime().getNil(); } break; } case 0: oldLength = -1; length = data.internal.getByteList().length(); if (length <= data.pos) { data.eof = true; if (buf == null) { buf = new ByteList(); } else { buf.setRealSize(0); } return makeString(getRuntime(), buf); } else { length -= data.pos; } break; default: getRuntime().newArgumentError(args.length, 0); } if (buf == null) { int internalLength = data.internal.getByteList().length(); if (internalLength > 0) { if (internalLength >= data.pos + length) { buf = new ByteList(data.internal.getByteList(), (int) data.pos, length); } else { int rest = (int) (data.internal.getByteList().length() - data.pos); if (length > rest) length = rest; buf = new ByteList(data.internal.getByteList(), (int) data.pos, length); } } } else { int rest = (int) (data.internal.getByteList().length() - data.pos); if (length > rest) length = rest; // Yow...this is still ugly byte[] target = buf.getUnsafeBytes(); if (target.length > length) { System.arraycopy( data.internal.getByteList().getUnsafeBytes(), (int) data.pos, target, 0, length); buf.setBegin(0); buf.setRealSize(length); } else { target = new byte[length]; System.arraycopy( data.internal.getByteList().getUnsafeBytes(), (int) data.pos, target, 0, length); buf.setBegin(0); buf.setRealSize(length); buf.setUnsafeBytes(target); } } if (buf == null) { if (!data.eof) buf = new ByteList(); length = 0; } else { length = buf.length(); data.pos += length; } if (oldLength < 0 || oldLength > length) data.eof = true; return originalString != null ? originalString : makeString(getRuntime(), buf); }