public SourceMarker(Source source) { this.markSource = new MarkSource(source); this.markBuffer = new Buffer(); this.userSource = Okio.buffer(markSource); this.userBuffer = userSource.getBuffer(); }
JsonUtf8Reader(BufferedSource source) { if (source == null) { throw new NullPointerException("source == null"); } this.source = source; this.buffer = source.getBuffer(); pushScope(JsonScope.EMPTY_DOCUMENT); }
/** * Consumes the field name of the specified length and the optional colon and its optional * trailing space. Returns the number of bytes skipped. */ private long skipNameAndDivider(long length) throws IOException { source.skip(length); if (source.getBuffer().getByte(0) == ':') { source.skip(1L); length++; if (source.getBuffer().getByte(0) == ' ') { source.skip(1); length++; } } return length; } }
/** * Returns true if the first bytes of {@link #source} are {@code key} followed by a colon or * a newline. */ private boolean isKey(ByteString key) throws IOException { if (source.rangeEquals(0, key)) { byte nextByte = source.getBuffer().getByte(key.size()); return nextByte == ':' || nextByte == '\r' || nextByte == '\n'; } return false; }
/** * Peeks up to {@code byteCount} bytes from the response body and returns them as a new response * body. If fewer than {@code byteCount} bytes are in the response body, the full response body is * returned. If more than {@code byteCount} bytes are in the response body, the returned value * will be truncated to {@code byteCount} bytes. * * <p>It is an error to call this method after the body has been consumed. * * <p><strong>Warning:</strong> this method loads the requested bytes into memory. Most * applications should set a modest limit on {@code byteCount}, such as 1 MiB. */ public ResponseBody peekBody(long byteCount) throws IOException { BufferedSource peeked = body.source().peek(); Buffer buffer = new Buffer(); peeked.request(byteCount); buffer.write(peeked, Math.min(byteCount, peeked.getBuffer().size())); return ResponseBody.create(body.contentType(), buffer.size(), buffer); }
/** Consumes {@code \r}, {@code \r\n}, or {@code \n} from {@link #source}. */ private void skipCrAndOrLf() throws IOException { if ((source.readByte() & 0xff) == '\r' && source.request(1) && source.getBuffer().getByte(0) == '\n') { source.skip(1); } }
/** Copy-constructor makes a deep copy for peeking. */ JsonUtf8Reader(JsonUtf8Reader copyFrom) { super(copyFrom); BufferedSource sourcePeek = copyFrom.source.peek(); this.source = sourcePeek; this.buffer = sourcePeek.getBuffer(); this.peeked = copyFrom.peeked; this.peekedLong = copyFrom.peekedLong; this.peekedNumberLength = copyFrom.peekedNumberLength; this.peekedString = copyFrom.peekedString; // Make sure our buffer has as many bytes as the source's buffer. This is necessary because // JsonUtf8Reader assumes any data it has peeked (like the peekedNumberLength) are buffered. try { sourcePeek.require(copyFrom.buffer.size()); } catch (IOException e) { throw new AssertionError(); } }
/** * Peeks up to {@code byteCount} bytes from the response body and returns them as a new response * body. If fewer than {@code byteCount} bytes are in the response body, the full response body is * returned. If more than {@code byteCount} bytes are in the response body, the returned value * will be truncated to {@code byteCount} bytes. * * <p>It is an error to call this method after the body has been consumed. * * <p><strong>Warning:</strong> this method loads the requested bytes into memory. Most * applications should set a modest limit on {@code byteCount}, such as 1 MiB. */ public ResponseBody peekBody(long byteCount) throws IOException { BufferedSource peeked = body.source().peek(); Buffer buffer = new Buffer(); peeked.request(byteCount); buffer.write(peeked, Math.min(byteCount, peeked.getBuffer().size())); return ResponseBody.create(body.contentType(), buffer.size(), buffer); }
@Test public void requireIncludesBufferBytes() throws Exception { Buffer source = new Buffer(); source.writeUtf8("b"); BufferedSource bufferedSource = Okio.buffer((Source) source); bufferedSource.getBuffer().writeUtf8("a"); bufferedSource.require(2); assertEquals("ab", bufferedSource.getBuffer().readUtf8(2)); }
if (!source.getBuffer().exhausted() || !sink.buffer().exhausted()) { throw new IOException("TLS tunnel buffered too many bytes!");
@Test public void requireTracksBufferFirst() throws Exception { Buffer source = new Buffer(); source.writeUtf8("bb"); BufferedSource bufferedSource = Okio.buffer((Source) source); bufferedSource.getBuffer().writeUtf8("aa"); bufferedSource.require(2); assertEquals(2, bufferedSource.getBuffer().size()); assertEquals(2, source.size()); }
@Test public void skipTracksBufferFirst() throws Exception { Buffer source = new Buffer(); source.writeUtf8("bb"); BufferedSource bufferedSource = Okio.buffer((Source) source); bufferedSource.getBuffer().writeUtf8("aa"); bufferedSource.skip(2); assertEquals(0, bufferedSource.getBuffer().size()); assertEquals(2, source.size()); }
BufferedSource source = responseBody.source(); Buffer buffer = source.getBuffer();
@Test public void factorySegmentSizes() throws Exception { sink.writeUtf8("abc"); sink.emit(); source.require(3); if (factory.isOneByteAtATime()) { assertEquals(Arrays.asList(1, 1, 1), TestUtil.segmentSizes(source.getBuffer())); } else { assertEquals(Collections.singletonList(3), TestUtil.segmentSizes(source.getBuffer())); } } }
switch (source.getBuffer().getByte(0)) { case '\r': case '\n':
@Test public void requireReadsOneSegmentAtATime() throws Exception { Buffer source = new Buffer(); source.writeUtf8(repeat('a', SEGMENT_SIZE)); source.writeUtf8(repeat('b', SEGMENT_SIZE)); BufferedSource bufferedSource = Okio.buffer((Source) source); bufferedSource.require(2); assertEquals(SEGMENT_SIZE, source.size()); assertEquals(SEGMENT_SIZE, bufferedSource.getBuffer().size()); }
@Test public void skipReadsOneSegmentAtATime() throws Exception { Buffer source = new Buffer(); source.writeUtf8(repeat('a', SEGMENT_SIZE)); source.writeUtf8(repeat('b', SEGMENT_SIZE)); BufferedSource bufferedSource = Okio.buffer((Source) source); bufferedSource.skip(2); assertEquals(SEGMENT_SIZE, source.size()); assertEquals(SEGMENT_SIZE - 2, bufferedSource.getBuffer().size()); }
@Test public void readAll() throws IOException { source.getBuffer().writeUtf8("abc"); sink.writeUtf8("def"); sink.emit(); Buffer sink = new Buffer(); assertEquals(6, source.readAll(sink)); assertEquals("abcdef", sink.readUtf8()); assertTrue(source.exhausted()); }
@Test public void rangeEqualsOnlyReadsUntilMismatch() throws IOException { assumeTrue(factory == Factory.ONE_BYTE_AT_A_TIME_BUFFERED_SOURCE); // Other sources read in chunks anyway. sink.writeUtf8("A man, a plan, a canal. Panama."); sink.emit(); assertFalse(source.rangeEquals(0, ByteString.encodeUtf8("A man."))); assertEquals("A man,", source.getBuffer().readUtf8()); }