/** * Perform a low-level read of the specified number of bytes into the specified byte list. The * incoming bytes will be appended to the byte list. This is equivalent to the read(2) POSIX * function, and like that function it ignores read and write buffers defined elsewhere. * * @param number the number of bytes to read * @param byteList the byte list on which to append the incoming bytes * @return the number of bytes actually read * @throws java.io.IOException if there is an exception during IO * @throws org.jruby.util.io.BadDescriptorException if the associated channel is already closed. * @see org.jruby.util.ByteList */ public int read(int number, ByteList byteList) throws IOException, BadDescriptorException { checkOpen(); byteList.ensure(byteList.length() + number); int bytesRead = read( ByteBuffer.wrap( byteList.getUnsafeBytes(), byteList.begin() + byteList.length(), number)); if (bytesRead > 0) { byteList.length(byteList.length() + bytesRead); } return bytesRead; }
/** * Copies bytes from the channel buffer into a destination <tt>ByteBuffer</tt> * * @param dst A <tt>ByteList</tt> to place the data in. * @param len The maximum number of bytes to copy. * @return The number of bytes copied. */ private final int copyBufferedBytes(ByteList dst, int len) { int bytesCopied = 0; dst.ensure(Math.min(len, bufferedInputBytesRemaining())); if (bytesCopied < len && ungotc != -1) { ++bytesCopied; dst.append((byte) ungotc); ungotc = -1; } // // Copy out any buffered bytes // if (bytesCopied < len && buffer.hasRemaining()) { int n = Math.min(buffer.remaining(), len - bytesCopied); dst.append(buffer, n); bytesCopied += n; } return bytesCopied; }
@JRubyMethod(required = 2, optional = 4) public IRubyObject primitive_convert(ThreadContext context, IRubyObject[] args) { Ruby runtime = context.runtime; RubyString input; RubyString output; int outputByteoffset = -1; int outputBytesize = 0; int flags = 0; int hashArg = -1; if (args.length > 2 && !args[2].isNil()) { if (args.length == 3 && args[2] instanceof RubyHash) { hashArg = 2; } else { outputByteoffset = (int) args[2].convertToInteger().getLongValue(); if (outputByteoffset < 0) throw runtime.newArgumentError("negative offset"); } } if (args.length > 3 && !args[3].isNil()) { if (args.length == 4 && args[3] instanceof RubyHash) { hashArg = 3; } else { outputBytesize = (int) args[3].convertToInteger().getLongValue(); if (outputBytesize < 0) throw runtime.newArgumentError("negative bytesize"); } } if (args.length > 4 && !args[4].isNil()) { if (args.length > 5 && !args[5].isNil()) { throw runtime.newArgumentError(args.length, 5); } if (args[4] instanceof RubyHash) { hashArg = 4; } else { flags = (int) args[4].convertToInteger().getLongValue(); } } IRubyObject opt = context.nil; if (hashArg != -1 && !(opt = TypeConverter.checkHashType(runtime, args[hashArg])).isNil()) { IRubyObject v = ((RubyHash) opt).op_aref(context, runtime.newSymbol("partial_input")); if (v.isTrue()) { flags |= EncodingUtils.ECONV_PARTIAL_INPUT; } v = ((RubyHash) opt).op_aref(context, runtime.newSymbol("after_output")); if (v.isTrue()) { flags |= EncodingUtils.ECONV_AFTER_OUTPUT; } } else { flags = 0; } ByteList inBytes; ByteList outBytes; if (args[0].isNil()) { inBytes = new ByteList(); } else { input = args[0].convertToString(); input.modify19(); inBytes = input.getByteList(); } output = args[1].convertToString(); output.modify19(); outBytes = output.getByteList(); if (outputByteoffset == -1) { outputByteoffset = outBytes.getRealSize(); } else if (outputByteoffset > outBytes.getRealSize()) { throw runtime.newArgumentError("offset too big"); } int outputByteEnd = outputByteoffset + outputBytesize; if (outputByteEnd > outBytes.getRealSize()) { outBytes.ensure(outputByteEnd); } RubyCoderResult result = transcoder.primitiveConvert( context, inBytes, output.getByteList(), outputByteoffset, outputBytesize, inBytes.getEncoding(), inBytes.getEncoding().isAsciiCompatible(), flags); outBytes.setEncoding( transcoder.outEncoding != null ? transcoder.outEncoding : inBytes.getEncoding()); return symbolFromResult(result, runtime, flags, context); }