Package 

Class Buffer

  • All Implemented Interfaces:
    com.mobwith.httpmodule.BufferedSink , com.mobwith.httpmodule.BufferedSource , com.mobwith.httpmodule.Sink , com.mobwith.httpmodule.Source , java.io.Closeable , java.io.Flushable , java.lang.AutoCloseable , java.lang.Cloneable , java.nio.channels.ByteChannel , java.nio.channels.Channel , java.nio.channels.ReadableByteChannel , java.nio.channels.WritableByteChannel

    
    public final class Buffer
     implements BufferedSource, BufferedSink, Cloneable, ByteChannel
                        

    A collection of bytes in memory.

    Moving data from one buffer to another is fast. Instead of copying bytes from one place in memory to another, this class just changes ownership of the underlying byte arrays.

    This buffer grows with your data. Just like ArrayList, each buffer starts small. It consumes only the memory it needs to.

    This buffer pools its byte arrays. When you allocate a byte array in Java, the runtime must zero-fill the requested array before returning it to you. Even if you're going to write over that space anyway. This class avoids zero-fill and GC churn by pooling byte arrays.

    • Nested Class Summary

      Nested Classes 
      Modifier and Type Class Description
      public final class Buffer.UnsafeCursor

      A handle to the underlying data in a buffer. This handle is unsafe because it does not enforceits own invariants. Instead, it assumes a careful user who has studied MobonOkio's implementationdetails and their consequences.

      Buffer Internals

      Most code should use {@code Buffer} as a black box: a class that holds 0 or more bytes ofdata with efficient APIs to append data to the end and to consume data from the front. Usuallythis is also the most efficient way to use buffers because it allows MobonOkio to employ severaloptimizations, including:

      • Fast Allocation: Buffers use a shared pool of memory that is notzero-filled before use.
      • Fast Resize: A buffer's capacity can change without copying itscontents.
      • Fast Move: Memory ownership can be reassigned from one buffer toanother.
      • Fast Copy: Multiple buffers can share the same underlying memory.
      • Fast Encoding and Decoding: Common operations like UTF-8 encoding anddecimal decoding do not require intermediate objects to be allocated.

      These optimizations all leverage the way MobonOkio stores data internally. MobonOkio Buffers areimplemented using a doubly-linked list of segments. Each segment is a contiguous range within a8 KiB {@code byte[]}. Each segment has two indexes, {@code start}, the offset of the firstbyte of the array containing application data, and {@code end}, the offset of the first bytebeyond {@code start} whose data is undefined.

      New buffers are empty and have no segments:

         {@code * * Buffer buffer = new Buffer(); * }
      We append 7 bytes of data to the end of our empty buffer. Internally, the buffer allocates asegment and writes its new data there. The lone segment has an 8 KiB byte array but only 7bytes of data:
         {@code * * buffer.writeUtf8("sealion"); * * // [ 's', 'e', 'a', 'l', 'i', 'o', 'n', '?', '?', '?', ...] * // ^ ^ * // start = 0 end = 7 * }
      When we read 4 bytes of data from the buffer, it finds its first segment and returns that datato us. As bytes are read the data is consumed. The segment tracks this by adjusting itsinternal indices.
         {@code * * buffer.readUtf8(4); // "seal" * * // [ 's', 'e', 'a', 'l', 'i', 'o', 'n', '?', '?', '?', ...] * // ^ ^ * // start = 4 end = 7 * }
      As we write data into a buffer we fill up its internal segments. When a write doesn't fit intoa buffer's last segment, additional segments are allocated and appended to the linked list ofsegments. Each segment has its own start and end indexes tracking where the user's data beginsand ends.
         {@code * * Buffer xoxo = new Buffer(); * xoxo.writeUtf8(Strings.repeat("xo", 5_000)); * * // [ 'x', 'o', 'x', 'o', 'x', 'o', 'x', 'o', ..., 'x', 'o', 'x', 'o'] * // ^ ^ * // start = 0 end = 8192 * // * // [ 'x', 'o', 'x', 'o', ..., 'x', 'o', 'x', 'o', '?', '?', '?', ...] * // ^ ^ * // start = 0 end = 1808 * }
      The start index is always inclusive and the end index is alwaysexclusive. The data preceding the start index is undefined, and the dataat and following the end index is undefined.

      After the last byte of a segment has been read, that segment may be returned to an internalsegment pool. In addition to reducing the need to do garbage collection, segment pooling alsosaves the JVM from needing to zero-fill byte arrays. MobonOkio doesn't need to zero-fill its arraysbecause it always writes memory before it reads it. But if you look at a segment in a debuggeryou may see its effects. In this example, one of the "xoxo" segments above is reused in anunrelated buffer:

         {@code * * Buffer abc = new Buffer(); * abc.writeUtf8("abc"); * * // [ 'a', 'b', 'c', 'o', 'x', 'o', 'x', 'o', ...] * // ^ ^ * // start = 0 end = 3 * }
      There is an optimization in {@code Buffer.clone()} and other methods that allows two segmentsto share the same underlying byte array. Clones can't write to the shared byte array; insteadthey allocate a new (private) segment early.
         {@code * * Buffer nana = new Buffer(); * nana.writeUtf8(Strings.repeat("na", 2_500)); * nana.readUtf8(2); // "na" * * // [ 'n', 'a', 'n', 'a', ..., 'n', 'a', 'n', 'a', '?', '?', '?', ...] * // ^ ^ * // start = 0 end = 5000 * * nana2 = nana.clone(); * nana2.writeUtf8("batman"); * * // [ 'n', 'a', 'n', 'a', ..., 'n', 'a', 'n', 'a', '?', '?', '?', ...] * // ^ ^ * // start = 0 end = 5000 * // * // [ 'b', 'a', 't', 'm', 'a', 'n', '?', '?', '?', ...] * // ^ ^ * // start = 0 end = 7 * }
      Segments are not shared when the shared region is small (ie. less than 1 KiB). This is intendedto prevent fragmentation in sharing-heavy use cases.Unsafe Cursor API

      This class exposes privileged access to the internal byte arrays of a buffer. A cursoreither references the data of a single segment, it is before the first segment ({@code * offset == -1}), or it is after the last segment ({@code offset == buffer.size}).

      Call seek to move the cursor to the segment that contains a specified offset. Afterseeking, data references the segment's internal byte array, start is thesegment's start and end is its end.

      Call next to advance the cursor to the next segment. This returns -1 if there areno further segments in the buffer.

      Use readUnsafe to create a cursor to read buffer data and to create a cursor to read and write buffer data. In either case,always call close when done with a cursor. This is convenient with Java 7'stry-with-resources syntax. In this example we read all of the bytes in a buffer into a bytearray:

         {@code * * byte[] bufferBytes = new byte[(int) buffer.size()]; * * try (UnsafeCursor cursor = buffer.readUnsafe()) { * while (cursor.next() != -1) { * System.arraycopy(cursor.data, cursor.start, * bufferBytes, (int) cursor.offset, cursor.end - cursor.start); * } * } * }

      Change the capacity of a buffer with resizeBuffer. This is only permitted forread+write cursors. The buffer's size always changes from the end: shrinking it removes bytesfrom the end; growing it adds capacity to the end.

      Warnings

      Most application developers should avoid this API. Those that must use this API shouldrespect these warnings.

      Don't mutate a cursor. This class has public, non-final fields because thatis convenient for low-level I/O frameworks. Never assign values to these fields; instead usethe cursor API to adjust these.

      Never mutate {@code data} unless you have read+write access. You are on thehonor system to never write the buffer in read-only mode. Read-only mode may be more efficientthan read+write mode because it does not need to make private copies of shared segments.

      Only access data in {@code [start..end)}. Other data in the byte arrayis undefined! It may contain private or sensitive data from other parts of your process.

      Always fill the new capacity when you grow a buffer. New capacity is notzero-filled and may contain data from other parts of your process. Avoid leaking thisinformation by always writing something to the newly-allocated capacity. Do not assume thatnew capacity will be filled with {@code 0}; it will not be.

      Do not access a buffer while is being accessed by a cursor. Even simpleread-only operations like clone are unsafe because they mark segments as shared.

      Do not hard-code the segment size in your application. It is possible thatsegment sizes will change with advances in hardware. Future versions of MobonOkio may even haveheterogeneous segment sizes.

      These warnings are intended to help you to use this API safely. It's here for developersthat need absolutely the most throughput. Since that's you, here's one final performance tip.You can reuse instances of this class if you like. Use the overloads of readUnsafe and readAndWriteUnsafe that take a cursor and close it after use.

    • Constructor Summary

      Constructors 
      Constructor Description
      Buffer()
    • Method Summary

      Modifier and Type Method Description
      final long size() Returns the number of bytes currently in this buffer.
      Buffer buffer() Returns this source's internal buffer.
      OutputStream outputStream() Returns an output stream that writes to this sink.
      Buffer emitCompleteSegments() Writes complete segments to the underlying sink, if one exists.
      BufferedSink emit() Writes all buffered data to the underlying sink, if one exists.
      boolean exhausted() Returns true if there are no more bytes in this source.
      void require(long byteCount) Returns when the buffer contains at least {@code byteCount} bytes.
      boolean request(long byteCount) Returns true when the buffer contains at least {@code byteCount} bytes, expanding it asnecessary.
      InputStream inputStream() Returns an input stream that reads from this source.
      final Buffer copyTo(OutputStream out) Copy the contents of this to {@code out}.
      final Buffer copyTo(OutputStream out, long offset, long byteCount) Copy {@code byteCount} bytes from this, starting at {@code offset}, to {@code out}.
      final Buffer copyTo(Buffer out, long offset, long byteCount) Copy {@code byteCount} bytes from this, starting at {@code offset}, to {@code out}.
      final Buffer writeTo(OutputStream out) Write the contents of this to {@code out}.
      final Buffer writeTo(OutputStream out, long byteCount) Write {@code byteCount} bytes from this to {@code out}.
      final Buffer readFrom(InputStream in) Read and exhaust bytes from {@code in} to this.
      final Buffer readFrom(InputStream in, long byteCount) Read {@code byteCount} bytes from {@code in} to this.
      final long completeSegmentByteCount() Returns the number of bytes in segments that are not writable.
      byte readByte() Removes a byte from this source and returns it.
      final byte getByte(long pos) Returns the byte at {@code pos}.
      short readShort() Removes two bytes from this source and returns a big-endian short.
      int readInt() Removes four bytes from this source and returns a big-endian int.
      long readLong() Removes eight bytes from this source and returns a big-endian long.
      short readShortLe() Removes two bytes from this source and returns a little-endian short.
      int readIntLe() Removes four bytes from this source and returns a little-endian int.
      long readLongLe() Removes eight bytes from this source and returns a little-endian long.
      long readDecimalLong() Reads a long from this source in signed decimal form (i.e., as a string in base 10 withoptional leading '-').
      long readHexadecimalUnsignedLong() Reads a long form this source in hexadecimal form (i.e., as a string in base 16).
      ByteString readByteString() Removes all bytes bytes from this and returns them as a byte string.
      ByteString readByteString(long byteCount) Removes {@code byteCount} bytes from this and returns them as a byte string.
      int select(Options options) Finds the first string in {@code options} that is a prefix of this buffer, consumes it fromthis buffer, and returns its index.
      void readFully(Buffer sink, long byteCount) Removes exactly {@code byteCount} bytes from this and appends them to {@code sink}.
      long readAll(Sink sink) Removes all bytes from this and appends them to {@code sink}.
      String readUtf8() Removes all bytes from this, decodes them as UTF-8, and returns the string.
      String readUtf8(long byteCount) Removes {@code byteCount} bytes from this, decodes them as UTF-8, and returns the string.
      String readString(Charset charset) Removes all bytes from this, decodes them as {@code charset}, and returns the string.
      String readString(long byteCount, Charset charset) Removes {@code byteCount} bytes from this, decodes them as {@code charset}, and returns thestring.
      String readUtf8Line() Removes and returns characters up to but not including the next line break.
      String readUtf8LineStrict() Removes and returns characters up to but not including the next line break.
      String readUtf8LineStrict(long limit) Like readUtf8LineStrict, except this allows the caller to specify the longestallowed match.
      int readUtf8CodePoint() Removes and returns a single UTF-8 code point, reading between 1 and 4 bytes as necessary.
      Array<byte> readByteArray() Removes all bytes from this and returns them as a byte array.
      Array<byte> readByteArray(long byteCount) Removes {@code byteCount} bytes from this and returns them as a byte array.
      int read(Array<byte> sink) Removes up to {@code sink.length} bytes from this and copies them into {@code sink}.
      void readFully(Array<byte> sink) Removes exactly {@code sink.length} bytes from this and copies them into {@code sink}.
      int read(Array<byte> sink, int offset, int byteCount) Removes up to {@code byteCount} bytes from this and copies them into {@code sink} at {@code * offset}.
      int read(ByteBuffer sink)
      final void clear() Discards all bytes in this buffer.
      void skip(long byteCount) Discards {@code byteCount} bytes from the head of this buffer.
      Buffer write(ByteString byteString)
      Buffer writeUtf8(String string) Encodes {@code string} in UTF-8 and writes it to this sink.
      Buffer writeUtf8(String string, int beginIndex, int endIndex) Encodes the characters at {@code beginIndex} up to {@code endIndex} from {@code string} inUTF-8 and writes it to this sink.
      Buffer writeUtf8CodePoint(int codePoint) Encodes {@code codePoint} in UTF-8 and writes it to this sink.
      Buffer writeString(String string, Charset charset) Encodes {@code string} in {@code charset} and writes it to this sink.
      Buffer writeString(String string, int beginIndex, int endIndex, Charset charset) Encodes the characters at {@code beginIndex} up to {@code endIndex} from {@code string} in {@code charset} and writes it to this sink.
      Buffer write(Array<byte> source) Like write, this writes a complete byte array tothis sink.
      Buffer write(Array<byte> source, int offset, int byteCount) Like write, this writes {@code byteCount} bytes of {@code source}, starting at {@code offset}.
      int write(ByteBuffer source)
      long writeAll(Source source) Removes all bytes from {@code source} and appends them to this sink.
      BufferedSink write(Source source, long byteCount) Removes {@code byteCount} bytes from {@code source} and appends them to this sink.
      Buffer writeByte(int b) Writes a byte to this sink.
      Buffer writeShort(int s) Writes a big-endian short to this sink using two bytes.
      Buffer writeShortLe(int s) Writes a little-endian short to this sink using two bytes.
      Buffer writeInt(int i) Writes a big-endian int to this sink using four bytes.
      Buffer writeIntLe(int i) Writes a little-endian int to this sink using four bytes.
      Buffer writeLong(long v) Writes a big-endian long to this sink using eight bytes.
      Buffer writeLongLe(long v) Writes a little-endian long to this sink using eight bytes.
      Buffer writeDecimalLong(long v) Writes a long to this sink in signed decimal form (i.e., as a string in base 10).
      Buffer writeHexadecimalUnsignedLong(long v) Writes a long to this sink in hexadecimal form (i.e., as a string in base 16).
      void write(Buffer source, long byteCount) Removes {@code byteCount} bytes from {@code source} and appends them to this.
      long read(Buffer sink, long byteCount) Removes at least 1, and up to {@code byteCount} bytes from this and appendsthem to {@code sink}.
      long indexOf(byte b) Equivalent to indexOf(b, 0).
      long indexOf(byte b, long fromIndex) Returns the index of {@code b} in this at or beyond {@code fromIndex}, or-1 if this buffer does not contain {@code b} in that range.
      long indexOf(byte b, long fromIndex, long toIndex) Returns the index of {@code b} if it is found in the range of {@code fromIndex} inclusiveto {@code toIndex} exclusive.
      long indexOf(ByteString bytes) Equivalent to indexOf(bytes, 0).
      long indexOf(ByteString bytes, long fromIndex) Returns the index of the first match for {@code bytes} in the buffer at or after {@code * fromIndex}.
      long indexOfElement(ByteString targetBytes) Equivalent to indexOfElement(targetBytes, 0).
      long indexOfElement(ByteString targetBytes, long fromIndex) Returns the first index in this buffer that is at or after {@code fromIndex} and that containsany of the bytes in {@code targetBytes}.
      boolean rangeEquals(long offset, ByteString bytes) Returns true if the bytes at {@code offset} in this source equal {@code bytes}.
      boolean rangeEquals(long offset, ByteString bytes, int bytesOffset, int byteCount) Returns true if {@code byteCount} bytes at {@code offset} in this source equal {@code bytes} at {@code bytesOffset}.
      void flush() Writes all buffered data to the underlying sink, if one exists.
      boolean isOpen()
      void close() Closes this source and releases the resources held by this source.
      Timeout timeout() Returns the timeout for this source.
      final ByteString md5() Returns the 128-bit MD5 hash of this buffer.
      final ByteString sha1() Returns the 160-bit SHA-1 hash of this buffer.
      final ByteString sha256() Returns the 256-bit SHA-256 hash of this buffer.
      final ByteString sha512() Returns the 512-bit SHA-512 hash of this buffer.
      final ByteString hmacSha1(ByteString key) Returns the 160-bit SHA-1 HMAC of this buffer.
      final ByteString hmacSha256(ByteString key) Returns the 256-bit SHA-256 HMAC of this buffer.
      final ByteString hmacSha512(ByteString key) Returns the 512-bit SHA-512 HMAC of this buffer.
      boolean equals(Object o)
      int hashCode()
      String toString() Returns a human-readable string that describes the contents of this buffer.
      Buffer clone() Returns a deep copy of this buffer.
      final ByteString snapshot() Returns an immutable copy of this buffer as a byte string.
      final ByteString snapshot(int byteCount) Returns an immutable copy of the first {@code byteCount} bytes of this buffer as a byte string.
      final Buffer.UnsafeCursor readUnsafe()
      final Buffer.UnsafeCursor readUnsafe(Buffer.UnsafeCursor unsafeCursor)
      final Buffer.UnsafeCursor readAndWriteUnsafe()
      final Buffer.UnsafeCursor readAndWriteUnsafe(Buffer.UnsafeCursor unsafeCursor)
      • Methods inherited from class com.mobwith.httpmodule.BufferedSource

        rangeEquals
      • Methods inherited from class java.io.Closeable

        close
      • Methods inherited from class java.nio.channels.ReadableByteChannel

        read
      • Methods inherited from class java.nio.channels.Channel

        isOpen
      • Methods inherited from class com.mobwith.httpmodule.BufferedSink

        emitCompleteSegments, write, write, write, writeByte, writeDecimalLong, writeHexadecimalUnsignedLong, writeInt, writeIntLe, writeLong, writeLongLe, writeShort, writeShortLe, writeString, writeString, writeUtf8, writeUtf8, writeUtf8CodePoint
      • Methods inherited from class java.io.Flushable

        flush
      • Methods inherited from class java.nio.channels.WritableByteChannel

        write
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Constructor Detail

      • Buffer

        Buffer()
    • Method Detail

      • size

         final long size()

        Returns the number of bytes currently in this buffer.

      • buffer

         Buffer buffer()

        Returns this source's internal buffer.

      • emitCompleteSegments

         Buffer emitCompleteSegments()

        Writes complete segments to the underlying sink, if one exists. Like flush, butweaker. Use this to limit the memory held in the buffer to a single segment. Typicallyapplication code will not need to call this: it is only necessary when application code writesdirectly to this sink's buffer.

        {@code * * BufferedSink b0 = new Buffer(); * BufferedSink b1 = MobonOkio.buffer(b0); * BufferedSink b2 = MobonOkio.buffer(b1); * * b2.buffer().write(new byte[20_000]); * assertEquals(20_000, b2.buffer().size()); * assertEquals( 0, b1.buffer().size()); * assertEquals( 0, b0.buffer().size()); * * b2.emitCompleteSegments(); * assertEquals( 3_616, b2.buffer().size()); * assertEquals( 0, b1.buffer().size()); * assertEquals(16_384, b0.buffer().size()); // This example assumes 8192 byte segments. * }
      • emit

         BufferedSink emit()

        Writes all buffered data to the underlying sink, if one exists. Like flush, butweaker. Call this before this buffered sink goes out of scope so that its data can reach itsdestination.

        {@code * * BufferedSink b0 = new Buffer(); * BufferedSink b1 = MobonOkio.buffer(b0); * BufferedSink b2 = MobonOkio.buffer(b1); * * b2.writeUtf8("hello"); * assertEquals(5, b2.buffer().size()); * assertEquals(0, b1.buffer().size()); * assertEquals(0, b0.buffer().size()); * * b2.emit(); * assertEquals(0, b2.buffer().size()); * assertEquals(5, b1.buffer().size()); * assertEquals(0, b0.buffer().size()); * * b1.emit(); * assertEquals(0, b2.buffer().size()); * assertEquals(0, b1.buffer().size()); * assertEquals(5, b0.buffer().size()); * }
      • exhausted

         boolean exhausted()

        Returns true if there are no more bytes in this source. This will block until there are bytesto read or the source is definitely exhausted.

      • require

         void require(long byteCount)

        Returns when the buffer contains at least {@code byteCount} bytes. Throws an java.io.EOFException if the source is exhausted before the required bytes can be read.

      • request

         boolean request(long byteCount)

        Returns true when the buffer contains at least {@code byteCount} bytes, expanding it asnecessary. Returns false if the source is exhausted before the requested bytes can be read.

      • copyTo

         final Buffer copyTo(OutputStream out, long offset, long byteCount)

        Copy {@code byteCount} bytes from this, starting at {@code offset}, to {@code out}.

      • copyTo

         final Buffer copyTo(Buffer out, long offset, long byteCount)

        Copy {@code byteCount} bytes from this, starting at {@code offset}, to {@code out}.

      • completeSegmentByteCount

         final long completeSegmentByteCount()

        Returns the number of bytes in segments that are not writable. This is thenumber of bytes that can be flushed immediately to an underlying sinkwithout harming throughput.

      • readByte

         byte readByte()

        Removes a byte from this source and returns it.

      • getByte

         final byte getByte(long pos)

        Returns the byte at {@code pos}.

      • readShort

         short readShort()

        Removes two bytes from this source and returns a big-endian short.

        {@code * * Buffer buffer = new Buffer() * .writeByte(0x7f) * .writeByte(0xff) * .writeByte(0x00) * .writeByte(0x0f); * assertEquals(4, buffer.size()); * * assertEquals(32767, buffer.readShort()); * assertEquals(2, buffer.size()); * * assertEquals(15, buffer.readShort()); * assertEquals(0, buffer.size()); * }
      • readInt

         int readInt()

        Removes four bytes from this source and returns a big-endian int.

        {@code * * Buffer buffer = new Buffer() * .writeByte(0x7f) * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0x00) * .writeByte(0x00) * .writeByte(0x00) * .writeByte(0x0f); * assertEquals(8, buffer.size()); * * assertEquals(2147483647, buffer.readInt()); * assertEquals(4, buffer.size()); * * assertEquals(15, buffer.readInt()); * assertEquals(0, buffer.size()); * }
      • readLong

         long readLong()

        Removes eight bytes from this source and returns a big-endian long.

        {@code * * Buffer buffer = new Buffer() * .writeByte(0x7f) * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0x00) * .writeByte(0x00) * .writeByte(0x00) * .writeByte(0x00) * .writeByte(0x00) * .writeByte(0x00) * .writeByte(0x00) * .writeByte(0x0f); * assertEquals(16, buffer.size()); * * assertEquals(9223372036854775807L, buffer.readLong()); * assertEquals(8, buffer.size()); * * assertEquals(15, buffer.readLong()); * assertEquals(0, buffer.size()); * }
      • readShortLe

         short readShortLe()

        Removes two bytes from this source and returns a little-endian short.

        {@code * * Buffer buffer = new Buffer() * .writeByte(0xff) * .writeByte(0x7f) * .writeByte(0x0f) * .writeByte(0x00); * assertEquals(4, buffer.size()); * * assertEquals(32767, buffer.readShortLe()); * assertEquals(2, buffer.size()); * * assertEquals(15, buffer.readShortLe()); * assertEquals(0, buffer.size()); * }
      • readIntLe

         int readIntLe()

        Removes four bytes from this source and returns a little-endian int.

        {@code * * Buffer buffer = new Buffer() * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0x7f) * .writeByte(0x0f) * .writeByte(0x00) * .writeByte(0x00) * .writeByte(0x00); * assertEquals(8, buffer.size()); * * assertEquals(2147483647, buffer.readIntLe()); * assertEquals(4, buffer.size()); * * assertEquals(15, buffer.readIntLe()); * assertEquals(0, buffer.size()); * }
      • readLongLe

         long readLongLe()

        Removes eight bytes from this source and returns a little-endian long.

        {@code * * Buffer buffer = new Buffer() * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0xff) * .writeByte(0x7f) * .writeByte(0x0f) * .writeByte(0x00) * .writeByte(0x00) * .writeByte(0x00) * .writeByte(0x00) * .writeByte(0x00) * .writeByte(0x00) * .writeByte(0x00); * assertEquals(16, buffer.size()); * * assertEquals(9223372036854775807L, buffer.readLongLe()); * assertEquals(8, buffer.size()); * * assertEquals(15, buffer.readLongLe()); * assertEquals(0, buffer.size()); * }
      • readDecimalLong

         long readDecimalLong()

        Reads a long from this source in signed decimal form (i.e., as a string in base 10 withoptional leading '-'). This will iterate until a non-digit character is found.

        {@code * * Buffer buffer = new Buffer() * .writeUtf8("8675309 -123 00001"); * * assertEquals(8675309L, buffer.readDecimalLong()); * assertEquals(' ', buffer.readByte()); * assertEquals(-123L, buffer.readDecimalLong()); * assertEquals(' ', buffer.readByte()); * assertEquals(1L, buffer.readDecimalLong()); * }
      • readHexadecimalUnsignedLong

         long readHexadecimalUnsignedLong()

        Reads a long form this source in hexadecimal form (i.e., as a string in base 16). This williterate until a non-hexadecimal character is found.

        {@code * * Buffer buffer = new Buffer() * .writeUtf8("ffff CAFEBABE 10"); * * assertEquals(65535L, buffer.readHexadecimalUnsignedLong()); * assertEquals(' ', buffer.readByte()); * assertEquals(0xcafebabeL, buffer.readHexadecimalUnsignedLong()); * assertEquals(' ', buffer.readByte()); * assertEquals(0x10L, buffer.readHexadecimalUnsignedLong()); * }
      • readByteString

         ByteString readByteString(long byteCount)

        Removes {@code byteCount} bytes from this and returns them as a byte string.

      • select

         int select(Options options)

        Finds the first string in {@code options} that is a prefix of this buffer, consumes it fromthis buffer, and returns its index. If no byte string in {@code options} is a prefix of thisbuffer this returns -1 and no bytes are consumed.

        This can be used as an alternative to readByteString or even readUtf8 ifthe set of expected values is known in advance.

        {@code * * Options FIELDS = Options.of( * ByteString.encodeUtf8("depth="), * ByteString.encodeUtf8("height="), * ByteString.encodeUtf8("width=")); * * Buffer buffer = new Buffer() * .writeUtf8("width=640\n") * .writeUtf8("height=480\n"); * * assertEquals(2, buffer.select(FIELDS)); * assertEquals(640, buffer.readDecimalLong()); * assertEquals('\n', buffer.readByte()); * assertEquals(1, buffer.select(FIELDS)); * assertEquals(480, buffer.readDecimalLong()); * assertEquals('\n', buffer.readByte()); * }
      • readFully

         void readFully(Buffer sink, long byteCount)

        Removes exactly {@code byteCount} bytes from this and appends them to {@code sink}. Throws an java.io.EOFException if the requested number of bytes cannot be read.

      • readAll

         long readAll(Sink sink)

        Removes all bytes from this and appends them to {@code sink}. Returns the total number of byteswritten to {@code sink} which will be 0 if this is exhausted.

      • readUtf8

         String readUtf8()

        Removes all bytes from this, decodes them as UTF-8, and returns the string. Returns the emptystring if this source is empty.

        {@code * * Buffer buffer = new Buffer() * .writeUtf8("Uh uh uh!") * .writeByte(' ') * .writeUtf8("You didn't say the magic word!"); * * assertEquals("Uh uh uh! You didn't say the magic word!", buffer.readUtf8()); * assertEquals(0, buffer.size()); * * assertEquals("", buffer.readUtf8()); * assertEquals(0, buffer.size()); * }
      • readUtf8

         String readUtf8(long byteCount)

        Removes {@code byteCount} bytes from this, decodes them as UTF-8, and returns the string.

        {@code * * Buffer buffer = new Buffer() * .writeUtf8("Uh uh uh!") * .writeByte(' ') * .writeUtf8("You didn't say the magic word!"); * assertEquals(40, buffer.size()); * * assertEquals("Uh uh uh! You ", buffer.readUtf8(14)); * assertEquals(26, buffer.size()); * * assertEquals("didn't say the", buffer.readUtf8(14)); * assertEquals(12, buffer.size()); * * assertEquals(" magic word!", buffer.readUtf8(12)); * assertEquals(0, buffer.size()); * }
      • readString

         String readString(Charset charset)

        Removes all bytes from this, decodes them as {@code charset}, and returns the string.

      • readString

         String readString(long byteCount, Charset charset)

        Removes {@code byteCount} bytes from this, decodes them as {@code charset}, and returns thestring.

      • readUtf8Line

        @Nullable() String readUtf8Line()

        Removes and returns characters up to but not including the next line break. A line break iseither {@code "\n"} or {@code "\r\n"}; these characters are not included in the result.

        {@code * * Buffer buffer = new Buffer() * .writeUtf8("I'm a hacker!\n") * .writeUtf8("That's what I said: you're a nerd.\n") * .writeUtf8("I prefer to be called a hacker!\n"); * assertEquals(81, buffer.size()); * * assertEquals("I'm a hacker!", buffer.readUtf8Line()); * assertEquals(67, buffer.size()); * * assertEquals("That's what I said: you're a nerd.", buffer.readUtf8Line()); * assertEquals(32, buffer.size()); * * assertEquals("I prefer to be called a hacker!", buffer.readUtf8Line()); * assertEquals(0, buffer.size()); * * assertEquals(null, buffer.readUtf8Line()); * assertEquals(0, buffer.size()); * }

        On the end of the stream this method returns null, just like . If the source doesn't end with a line break then an implicit linebreak is assumed. Null is returned once the source is exhausted. Use this for human-generateddata, where a trailing line break is optional.

      • readUtf8LineStrict

         String readUtf8LineStrict()

        Removes and returns characters up to but not including the next line break. A line break iseither {@code "\n"} or {@code "\r\n"}; these characters are not included in the result.

        On the end of the stream this method throws. Every call must consume either'\r\n' or '\n'. If these characters are absent in the stream, an java.io.EOFException is thrown. Use this for machine-generated data where a missing line break implies truncatedinput.

      • readUtf8LineStrict

         String readUtf8LineStrict(long limit)

        Like readUtf8LineStrict, except this allows the caller to specify the longestallowed match. Use this to protect against streams that may not include {@code "\n"} or {@code "\r\n"}.

        The returned string will have at most {@code limit} UTF-8 bytes, and the maximum numberof bytes scanned is {@code limit + 2}. If {@code limit == 0} this will always throwan {@code EOFException} because no bytes will be scanned.

        This method is safe. No bytes are discarded if the match fails, and the caller is freeto try another match:

        {@code * * Buffer buffer = new Buffer(); * buffer.writeUtf8("12345\r\n"); * * // This will throw! There must be \r\n or \n at the limit or before it. * buffer.readUtf8LineStrict(4); * * // No bytes have been consumed so the caller can retry. * assertEquals("12345", buffer.readUtf8LineStrict(5)); * }
      • readUtf8CodePoint

         int readUtf8CodePoint()

        Removes and returns a single UTF-8 code point, reading between 1 and 4 bytes as necessary.

        If this source is exhausted before a complete code point can be read, this throws an and consumes no input.

        If this source doesn't start with a properly-encoded UTF-8 code point, this method willremove 1 or more non-UTF-8 bytes and return the replacement character ({@code U+FFFD}). Thiscovers encoding problems (the input is not properly-encoded UTF-8), characters out of range(beyond the 0x10ffff limit of Unicode), code points for UTF-16 surrogates (U+d800..U+dfff) andoverlong encodings (such as {@code 0xc080} for the NUL character in modified UTF-8).

      • readByteArray

         Array<byte> readByteArray()

        Removes all bytes from this and returns them as a byte array.

      • readByteArray

         Array<byte> readByteArray(long byteCount)

        Removes {@code byteCount} bytes from this and returns them as a byte array.

      • read

         int read(Array<byte> sink)

        Removes up to {@code sink.length} bytes from this and copies them into {@code sink}. Returnsthe number of bytes read, or -1 if this source is exhausted.

      • readFully

         void readFully(Array<byte> sink)

        Removes exactly {@code sink.length} bytes from this and copies them into {@code sink}. Throwsan java.io.EOFException if the requested number of bytes cannot be read.

      • read

         int read(Array<byte> sink, int offset, int byteCount)

        Removes up to {@code byteCount} bytes from this and copies them into {@code sink} at {@code * offset}. Returns the number of bytes read, or -1 if this source is exhausted.

      • clear

         final void clear()

        Discards all bytes in this buffer. Calling this method when you're donewith a buffer will return its segments to the pool.

      • skip

         void skip(long byteCount)

        Discards {@code byteCount} bytes from the head of this buffer.

      • writeUtf8

         Buffer writeUtf8(String string)

        Encodes {@code string} in UTF-8 and writes it to this sink.

        {@code * * Buffer buffer = new Buffer(); * buffer.writeUtf8("Uh uh uh!"); * buffer.writeByte(' '); * buffer.writeUtf8("You didn't say the magic word!"); * * assertEquals("Uh uh uh! You didn't say the magic word!", buffer.readUtf8()); * }
      • writeUtf8

         Buffer writeUtf8(String string, int beginIndex, int endIndex)

        Encodes the characters at {@code beginIndex} up to {@code endIndex} from {@code string} inUTF-8 and writes it to this sink.

        {@code * * Buffer buffer = new Buffer(); * buffer.writeUtf8("I'm a hacker!\n", 6, 12); * buffer.writeByte(' '); * buffer.writeUtf8("That's what I said: you're a nerd.\n", 29, 33); * buffer.writeByte(' '); * buffer.writeUtf8("I prefer to be called a hacker!\n", 24, 31); * * assertEquals("hacker nerd hacker!", buffer.readUtf8()); * }
      • writeUtf8CodePoint

         Buffer writeUtf8CodePoint(int codePoint)

        Encodes {@code codePoint} in UTF-8 and writes it to this sink.

      • writeString

         Buffer writeString(String string, int beginIndex, int endIndex, Charset charset)

        Encodes the characters at {@code beginIndex} up to {@code endIndex} from {@code string} in {@code charset} and writes it to this sink.

      • write

         Buffer write(Array<byte> source, int offset, int byteCount)

        Like write, this writes {@code byteCount} bytes of {@code source}, starting at {@code offset}.

      • writeAll

         long writeAll(Source source)

        Removes all bytes from {@code source} and appends them to this sink. Returns thenumber of bytes read which will be 0 if {@code source} is exhausted.

      • write

         BufferedSink write(Source source, long byteCount)

        Removes {@code byteCount} bytes from {@code source} and appends them to this sink.

      • writeShort

         Buffer writeShort(int s)

        Writes a big-endian short to this sink using two bytes.

        {@code * * Buffer buffer = new Buffer(); * buffer.writeShort(32767); * buffer.writeShort(15); * * assertEquals(4, buffer.size()); * assertEquals((byte) 0x7f, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x0f, buffer.readByte()); * assertEquals(0, buffer.size()); * }
      • writeShortLe

         Buffer writeShortLe(int s)

        Writes a little-endian short to this sink using two bytes.

        {@code * * Buffer buffer = new Buffer(); * buffer.writeShortLe(32767); * buffer.writeShortLe(15); * * assertEquals(4, buffer.size()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0x7f, buffer.readByte()); * assertEquals((byte) 0x0f, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals(0, buffer.size()); * }
      • writeInt

         Buffer writeInt(int i)

        Writes a big-endian int to this sink using four bytes.

        {@code * * Buffer buffer = new Buffer(); * buffer.writeInt(2147483647); * buffer.writeInt(15); * * assertEquals(8, buffer.size()); * assertEquals((byte) 0x7f, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x0f, buffer.readByte()); * assertEquals(0, buffer.size()); * }
      • writeIntLe

         Buffer writeIntLe(int i)

        Writes a little-endian int to this sink using four bytes.

        {@code * * Buffer buffer = new Buffer(); * buffer.writeIntLe(2147483647); * buffer.writeIntLe(15); * * assertEquals(8, buffer.size()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0x7f, buffer.readByte()); * assertEquals((byte) 0x0f, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals(0, buffer.size()); * }
      • writeLong

         Buffer writeLong(long v)

        Writes a big-endian long to this sink using eight bytes.

        {@code * * Buffer buffer = new Buffer(); * buffer.writeLong(9223372036854775807L); * buffer.writeLong(15); * * assertEquals(16, buffer.size()); * assertEquals((byte) 0x7f, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x0f, buffer.readByte()); * assertEquals(0, buffer.size()); * }
      • writeLongLe

         Buffer writeLongLe(long v)

        Writes a little-endian long to this sink using eight bytes.

        {@code * * Buffer buffer = new Buffer(); * buffer.writeLongLe(9223372036854775807L); * buffer.writeLongLe(15); * * assertEquals(16, buffer.size()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0xff, buffer.readByte()); * assertEquals((byte) 0x7f, buffer.readByte()); * assertEquals((byte) 0x0f, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals((byte) 0x00, buffer.readByte()); * assertEquals(0, buffer.size()); * }
      • writeDecimalLong

         Buffer writeDecimalLong(long v)

        Writes a long to this sink in signed decimal form (i.e., as a string in base 10).

        {@code * * Buffer buffer = new Buffer(); * buffer.writeDecimalLong(8675309L); * buffer.writeByte(' '); * buffer.writeDecimalLong(-123L); * buffer.writeByte(' '); * buffer.writeDecimalLong(1L); * * assertEquals("8675309 -123 1", buffer.readUtf8()); * }
      • writeHexadecimalUnsignedLong

         Buffer writeHexadecimalUnsignedLong(long v)

        Writes a long to this sink in hexadecimal form (i.e., as a string in base 16).

        {@code * * Buffer buffer = new Buffer(); * buffer.writeHexadecimalUnsignedLong(65535L); * buffer.writeByte(' '); * buffer.writeHexadecimalUnsignedLong(0xcafebabeL); * buffer.writeByte(' '); * buffer.writeHexadecimalUnsignedLong(0x10L); * * assertEquals("ffff cafebabe 10", buffer.readUtf8()); * }
      • write

         void write(Buffer source, long byteCount)

        Removes {@code byteCount} bytes from {@code source} and appends them to this.

      • read

         long read(Buffer sink, long byteCount)

        Removes at least 1, and up to {@code byteCount} bytes from this and appendsthem to {@code sink}. Returns the number of bytes read, or -1 if thissource is exhausted.

      • indexOf

         long indexOf(byte b, long fromIndex)

        Returns the index of {@code b} in this at or beyond {@code fromIndex}, or-1 if this buffer does not contain {@code b} in that range.

      • indexOf

         long indexOf(byte b, long fromIndex, long toIndex)

        Returns the index of {@code b} if it is found in the range of {@code fromIndex} inclusiveto {@code toIndex} exclusive. If {@code b} isn't found, or if {@code fromIndex == toIndex},then -1 is returned.

        The scan terminates at either {@code toIndex} or the end of the buffer, whichever comesfirst. The maximum number of bytes scanned is {@code toIndex-fromIndex}.

      • indexOf

         long indexOf(ByteString bytes, long fromIndex)

        Returns the index of the first match for {@code bytes} in the buffer at or after {@code * fromIndex}. This expands the buffer as necessary until {@code bytes} is found. This reads anunbounded number of bytes into the buffer. Returns -1 if the stream is exhausted before therequested bytes are found.

        {@code * * ByteString MOVE = ByteString.encodeUtf8("move"); * * Buffer buffer = new Buffer(); * buffer.writeUtf8("Don't move! He can't see us if we don't move."); * * assertEquals(6, buffer.indexOf(MOVE)); * assertEquals(40, buffer.indexOf(MOVE, 12)); * }
      • indexOfElement

         long indexOfElement(ByteString targetBytes, long fromIndex)

        Returns the first index in this buffer that is at or after {@code fromIndex} and that containsany of the bytes in {@code targetBytes}. This expands the buffer as necessary until a targetbyte is found. This reads an unbounded number of bytes into the buffer. Returns -1 if thestream is exhausted before the requested byte is found.

        {@code * * ByteString ANY_VOWEL = ByteString.encodeUtf8("AEOIUaeoiu"); * * Buffer buffer = new Buffer(); * buffer.writeUtf8("Dr. Alan Grant"); * * assertEquals(4, buffer.indexOfElement(ANY_VOWEL)); // 'A' in 'Alan'. * assertEquals(11, buffer.indexOfElement(ANY_VOWEL, 9)); // 'a' in 'Grant'. * }
      • rangeEquals

         boolean rangeEquals(long offset, ByteString bytes)

        Returns true if the bytes at {@code offset} in this source equal {@code bytes}. This expandsthe buffer as necessary until a byte does not match, all bytes are matched, or if the streamis exhausted before enough bytes could determine a match.

        {@code * * ByteString simonSays = ByteString.encodeUtf8("Simon says:"); * * Buffer standOnOneLeg = new Buffer().writeUtf8("Simon says: Stand on one leg."); * assertTrue(standOnOneLeg.rangeEquals(0, simonSays)); * * Buffer payMeMoney = new Buffer().writeUtf8("Pay me $1,000,000."); * assertFalse(payMeMoney.rangeEquals(0, simonSays)); * }
      • rangeEquals

         boolean rangeEquals(long offset, ByteString bytes, int bytesOffset, int byteCount)

        Returns true if {@code byteCount} bytes at {@code offset} in this source equal {@code bytes} at {@code bytesOffset}. This expands the buffer as necessary until a byte does not match, allbytes are matched, or if the stream is exhausted before enough bytes could determine a match.

      • flush

         void flush()

        Writes all buffered data to the underlying sink, if one exists. Then that sink is recursivelyflushed which pushes data as far as possible towards its ultimate destination. Typically thatdestination is a network socket or file.

        {@code * * BufferedSink b0 = new Buffer(); * BufferedSink b1 = MobonOkio.buffer(b0); * BufferedSink b2 = MobonOkio.buffer(b1); * * b2.writeUtf8("hello"); * assertEquals(5, b2.buffer().size()); * assertEquals(0, b1.buffer().size()); * assertEquals(0, b0.buffer().size()); * * b2.flush(); * assertEquals(0, b2.buffer().size()); * assertEquals(0, b1.buffer().size()); * assertEquals(5, b0.buffer().size()); * }
      • close

         void close()

        Closes this source and releases the resources held by this source. It is anerror to read a closed source. It is safe to close a source more than once.

      • md5

         final ByteString md5()

        Returns the 128-bit MD5 hash of this buffer.

      • sha1

         final ByteString sha1()

        Returns the 160-bit SHA-1 hash of this buffer.

      • sha256

         final ByteString sha256()

        Returns the 256-bit SHA-256 hash of this buffer.

      • sha512

         final ByteString sha512()

        Returns the 512-bit SHA-512 hash of this buffer.

      • toString

         String toString()

        Returns a human-readable string that describes the contents of this buffer. Typically thisis a string like {@code [text=Hello]} or {@code [hex=0000ffff]}.

      • clone

         Buffer clone()

        Returns a deep copy of this buffer.

      • snapshot

         final ByteString snapshot()

        Returns an immutable copy of this buffer as a byte string.

      • snapshot

         final ByteString snapshot(int byteCount)

        Returns an immutable copy of the first {@code byteCount} bytes of this buffer as a byte string.