/** * Used to add additional HTTP message chunk content to {@link #inputContentBuffer}. * * @param requestedLen how much content should attempt to be read, <code>-1</code> means read till * the end of the message. * @return the number of bytes actually read * @throws IOException if an I/O error occurs while reading content */ private int fill(final int requestedLen) throws IOException { int read = 0; while ((requestedLen == -1 || read < requestedLen) && httpHeader.isExpectContent()) { final HttpContent c = blockingRead(); final boolean isLast = c.isLast(); // Check if HttpContent is chunked message trailer w/ headers checkHttpTrailer(c); final Buffer b; try { b = c.getContent(); } catch (HttpBrokenContentException e) { final Throwable cause = e.getCause(); throw Exceptions.makeIOException(cause != null ? cause : e); } read += b.remaining(); updateInputContentBuffer(b); c.recycle(); if (isLast) { finished(); break; } } if (read > 0 || requestedLen == 0) { return read; } return -1; }
/** @see java.io.Reader#ready() */ public boolean ready() { if (closed) { return false; } if (!processingChars) { throw new IllegalStateException(); } return (inputContentBuffer.hasRemaining() || httpHeader.isExpectContent()); }
/** * Used to convert bytes to chars. * * @param requestedLen how much content should attempt to be read * @return the number of chars actually read * @throws IOException if an I/O error occurs while reading content */ private int fillChars(final int requestedLen, final CharBuffer dst) throws IOException { int read = 0; // 1) Check pre-decoded singleCharBuf if (dst != singleCharBuf && singleCharBuf.hasRemaining()) { dst.put(singleCharBuf.get()); read = 1; } // 2) Decode available byte[] -> char[] if (inputContentBuffer.hasRemaining()) { read += fillAvailableChars(requestedLen - read, dst); } if (read >= requestedLen) { dst.flip(); return read; } // 3) If we don't expect more data - return what we've read so far if (!httpHeader.isExpectContent()) { dst.flip(); return read > 0 ? read : -1; } // 4) Try to read more data (we may block) CharsetDecoder decoderLocal = getDecoder(); boolean isNeedMoreInput = false; // true, if content in composite buffer is not enough to produce even 1 char boolean last = false; while (read < requestedLen && httpHeader.isExpectContent()) { if (isNeedMoreInput || !inputContentBuffer.hasRemaining()) { final HttpContent c = blockingRead(); updateInputContentBuffer(c.getContent()); last = c.isLast(); c.recycle(); isNeedMoreInput = false; } final ByteBuffer bytes = inputContentBuffer.toByteBuffer(); final int bytesPos = bytes.position(); final int dstPos = dst.position(); final CoderResult result = decoderLocal.decode(bytes, dst, false); final int producedChars = dst.position() - dstPos; final int consumedBytes = bytes.position() - bytesPos; read += producedChars; if (consumedBytes > 0) { bytes.position(bytesPos); inputContentBuffer.position(inputContentBuffer.position() + consumedBytes); if (readAheadLimit == -1) { inputContentBuffer.shrink(); } } else { isNeedMoreInput = true; } if (last || result == CoderResult.OVERFLOW) { break; } } dst.flip(); if (last && read == 0) { read = -1; } return read; }