13c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller/*
23c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Copyright (C) 2014 Square, Inc.
33c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
43c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License");
53c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * you may not use this file except in compliance with the License.
63c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * You may obtain a copy of the License at
73c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
83c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *      http://www.apache.org/licenses/LICENSE-2.0
93c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Unless required by applicable law or agreed to in writing, software
113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS,
123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * See the License for the specific language governing permissions and
143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * limitations under the License.
153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */
163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpackage okio;
173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.EOFException;
19c6bd683320121544811f481709b3fdbcbe9b3866Neil Fullerimport java.io.IOException;
203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.InputStream;
213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.OutputStream;
223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.security.MessageDigest;
233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.security.NoSuchAlgorithmException;
243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.ArrayList;
253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.Collections;
263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.List;
273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static okio.Util.UTF_8;
293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static okio.Util.checkOffsetAndCount;
30c6bd683320121544811f481709b3fdbcbe9b3866Neil Fullerimport static okio.Util.reverseBytesLong;
313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller/**
333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * A collection of bytes in memory.
343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * <p><strong>Moving data from one OkBuffer to another is fast.</strong> Instead
363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * of copying bytes from one place in memory to another, this class just changes
37c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller * ownership of the underlying byte arrays.
383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * <p><strong>This buffer grows with your data.</strong> Just like ArrayList,
403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * each OkBuffer starts small. It consumes only the memory it needs to.
413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * <p><strong>This buffer pools its byte arrays.</strong> When you allocate a
433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * byte array in Java, the runtime must zero-fill the requested array before
443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * returning it to you. Even if you're going to write over that space anyway.
453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * This class avoids zero-fill and GC churn by pooling byte arrays.
463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */
473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpublic final class OkBuffer implements BufferedSource, BufferedSink, Cloneable {
483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  Segment head;
493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  long size;
503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public OkBuffer() {
523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /** Returns the number of bytes currently in this buffer. */
553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public long size() {
563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return size;
573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public OkBuffer buffer() {
603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return this;
613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public OutputStream outputStream() {
643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return new OutputStream() {
653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      @Override public void write(int b) {
663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        writeByte((byte) b);
673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      @Override public void write(byte[] data, int offset, int byteCount) {
703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        OkBuffer.this.write(data, offset, byteCount);
713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      @Override public void flush() {
743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      @Override public void close() {
773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      @Override public String toString() {
803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        return this + ".outputStream()";
813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    };
833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public OkBuffer emitCompleteSegments() {
863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return this; // Nowhere to emit to!
873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public boolean exhausted() {
903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return size == 0;
913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public void require(long byteCount) throws EOFException {
943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (this.size < byteCount) throw new EOFException();
953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public InputStream inputStream() {
983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return new InputStream() {
993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      @Override public int read() {
1003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        return readByte() & 0xff;
1013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
1023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      @Override public int read(byte[] sink, int offset, int byteCount) {
1043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        return OkBuffer.this.read(sink, offset, byteCount);
1053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
1063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      @Override public int available() {
1083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        return (int) Math.min(size, Integer.MAX_VALUE);
1093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
1103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      @Override public void close() {
1123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
1133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      @Override public String toString() {
1153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        return OkBuffer.this + ".inputStream()";
1163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
1173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    };
1183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /**
1213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * Returns the number of bytes in segments that are not writable. This is the
1223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * number of bytes that can be flushed immediately to an underlying sink
1233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * without harming throughput.
1243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   */
1253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public long completeSegmentByteCount() {
1263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    long result = size;
1273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (result == 0) return 0;
1283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // Omit the tail if it's still writable.
1303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment tail = head.prev;
1313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (tail.limit < Segment.SIZE) {
1323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      result -= tail.limit - tail.pos;
1333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
1343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return result;
1363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public byte readByte() {
1393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (size == 0) throw new IllegalStateException("size == 0");
1403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment segment = head;
1423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int pos = segment.pos;
1433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int limit = segment.limit;
1443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    byte[] data = segment.data;
1463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    byte b = data[pos++];
1473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    size -= 1;
1483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (pos == limit) {
1503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      head = segment.pop();
1513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      SegmentPool.INSTANCE.recycle(segment);
1523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    } else {
1533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      segment.pos = pos;
1543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
1553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return b;
1573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
159c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  /** Returns the byte at {@code pos}. */
160c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  public byte getByte(long pos) {
161c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    checkOffsetAndCount(size, pos, 1);
1623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    for (Segment s = head; true; s = s.next) {
1633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      int segmentByteCount = s.limit - s.pos;
164c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller      if (pos < segmentByteCount) return s.data[s.pos + (int) pos];
165c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller      pos -= segmentByteCount;
1663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
1673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public short readShort() {
170c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    if (size < 2) throw new IllegalStateException("size < 2: " + size);
1713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment segment = head;
1733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int pos = segment.pos;
1743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int limit = segment.limit;
1753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // If the short is split across multiple segments, delegate to readByte().
1773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (limit - pos < 2) {
1783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      int s = (readByte() & 0xff) << 8
1793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          |   (readByte() & 0xff);
1803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return (short) s;
1813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
1823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    byte[] data = segment.data;
1843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int s = (data[pos++] & 0xff) << 8
1853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        |   (data[pos++] & 0xff);
1863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    size -= 2;
1873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (pos == limit) {
1893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      head = segment.pop();
1903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      SegmentPool.INSTANCE.recycle(segment);
1913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    } else {
1923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      segment.pos = pos;
1933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
1943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return (short) s;
1963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public int readInt() {
199c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    if (size < 4) throw new IllegalStateException("size < 4: " + size);
2003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment segment = head;
2023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int pos = segment.pos;
2033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int limit = segment.limit;
2043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // If the int is split across multiple segments, delegate to readByte().
2063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (limit - pos < 4) {
2073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return (readByte() & 0xff) << 24
2083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          |  (readByte() & 0xff) << 16
209c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller          |  (readByte() & 0xff) <<  8
2103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          |  (readByte() & 0xff);
2113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
2123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    byte[] data = segment.data;
2143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int i = (data[pos++] & 0xff) << 24
2153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        |   (data[pos++] & 0xff) << 16
216c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller        |   (data[pos++] & 0xff) <<  8
2173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        |   (data[pos++] & 0xff);
2183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    size -= 4;
2193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (pos == limit) {
2213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      head = segment.pop();
2223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      SegmentPool.INSTANCE.recycle(segment);
2233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    } else {
2243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      segment.pos = pos;
2253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
2263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return i;
2283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
2293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
230c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Override public long readLong() {
231c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    if (size < 8) throw new IllegalStateException("size < 8: " + size);
232c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
233c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    Segment segment = head;
234c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    int pos = segment.pos;
235c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    int limit = segment.limit;
236c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
237c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    // If the long is split across multiple segments, delegate to readInt().
238c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    if (limit - pos < 8) {
239c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller      return (readInt() & 0xffffffffL) << 32
240c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller          |  (readInt() & 0xffffffffL);
241c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    }
242c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
243c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    byte[] data = segment.data;
244c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    long v = (data[pos++] & 0xffL) << 56
245c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller        |    (data[pos++] & 0xffL) << 48
246c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller        |    (data[pos++] & 0xffL) << 40
247c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller        |    (data[pos++] & 0xffL) << 32
248c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller        |    (data[pos++] & 0xffL) << 24
249c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller        |    (data[pos++] & 0xffL) << 16
250c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller        |    (data[pos++] & 0xffL) <<  8
251c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller        |    (data[pos++] & 0xffL);
252c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    size -= 8;
253c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
254c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    if (pos == limit) {
255c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller      head = segment.pop();
256c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller      SegmentPool.INSTANCE.recycle(segment);
257c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    } else {
258c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller      segment.pos = pos;
259c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    }
260c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
261c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    return v;
262c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  }
263c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
264c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Override public short readShortLe() {
2653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return Util.reverseBytesShort(readShort());
2663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
2673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
268c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Override public int readIntLe() {
2693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return Util.reverseBytesInt(readInt());
2703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
2713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
272c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Override public long readLongLe() {
273c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    return Util.reverseBytesLong(readLong());
274c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  }
275c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
276c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Override public ByteString readByteString(long byteCount) {
2773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return new ByteString(readBytes(byteCount));
2783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
2793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
280c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Override public String readUtf8(long byteCount) {
2813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    checkOffsetAndCount(this.size, 0, byteCount);
2823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (byteCount > Integer.MAX_VALUE) {
2833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      throw new IllegalArgumentException("byteCount > Integer.MAX_VALUE: " + byteCount);
2843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
2853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (byteCount == 0) return "";
2863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment head = this.head;
2883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (head.pos + byteCount > head.limit) {
2893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      // If the string spans multiple segments, delegate to readBytes().
2903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return new String(readBytes(byteCount), Util.UTF_8);
2913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
2923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    String result = new String(head.data, head.pos, (int) byteCount, UTF_8);
2943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    head.pos += byteCount;
2953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    this.size -= byteCount;
2963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (head.pos == head.limit) {
2983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      this.head = head.pop();
2993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      SegmentPool.INSTANCE.recycle(head);
3003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
3013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return result;
3033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
3043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
305c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Override public String readUtf8Line() throws IOException {
3063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    long newline = indexOf((byte) '\n');
3073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (newline == -1) {
3093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return size != 0 ? readUtf8(size) : null;
3103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
3113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
312c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    return readUtf8Line(newline);
313c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  }
314c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
315c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Override public String readUtf8LineStrict() throws IOException {
316c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    long newline = indexOf((byte) '\n');
317c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    if (newline == -1) throw new EOFException();
318c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    return readUtf8Line(newline);
319c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  }
320c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
321c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  String readUtf8Line(long newline) {
3223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (newline > 0 && getByte(newline - 1) == '\r') {
3233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      // Read everything until '\r\n', then skip the '\r\n'.
3243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      String result = readUtf8((newline - 1));
3253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      skip(2);
3263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return result;
3273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    } else {
3293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      // Read everything until '\n', then skip the '\n'.
3303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      String result = readUtf8(newline);
3313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      skip(1);
3323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return result;
3333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
3343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
3353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private byte[] readBytes(long byteCount) {
3373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    checkOffsetAndCount(this.size, 0, byteCount);
3383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (byteCount > Integer.MAX_VALUE) {
3393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      throw new IllegalArgumentException("byteCount > Integer.MAX_VALUE: " + byteCount);
3403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
3413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int offset = 0;
3433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    byte[] result = new byte[(int) byteCount];
3443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    while (offset < byteCount) {
3463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      int toCopy = (int) Math.min(byteCount - offset, head.limit - head.pos);
3473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      System.arraycopy(head.data, head.pos, result, offset, toCopy);
3483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      offset += toCopy;
3503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      head.pos += toCopy;
3513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      if (head.pos == head.limit) {
3533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        Segment toRecycle = head;
3543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        head = toRecycle.pop();
3553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        SegmentPool.INSTANCE.recycle(toRecycle);
3563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
3573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
3583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    this.size -= byteCount;
3603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return result;
3613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
3623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /** Like {@link InputStream#read}. */
3643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  int read(byte[] sink, int offset, int byteCount) {
3653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment s = this.head;
366c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    if (s == null) return -1;
3673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int toCopy = Math.min(byteCount, s.limit - s.pos);
3683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    System.arraycopy(s.data, s.pos, sink, offset, toCopy);
3693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    s.pos += toCopy;
3713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    this.size -= toCopy;
3723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (s.pos == s.limit) {
3743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      this.head = s.pop();
3753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      SegmentPool.INSTANCE.recycle(s);
3763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
3773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return toCopy;
3793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
3803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /**
3823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * Discards all bytes in this buffer. Calling this method when you're done
3833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * with a buffer will return its segments to the pool.
3843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   */
3853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public void clear() {
3863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    skip(size);
3873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
3883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /** Discards {@code byteCount} bytes from the head of this buffer. */
390c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Override public void skip(long byteCount) {
3913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    checkOffsetAndCount(this.size, 0, byteCount);
3923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    this.size -= byteCount;
3943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    while (byteCount > 0) {
3953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      int toSkip = (int) Math.min(byteCount, head.limit - head.pos);
3963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      byteCount -= toSkip;
3973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      head.pos += toSkip;
3983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
3993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      if (head.pos == head.limit) {
4003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        Segment toRecycle = head;
4013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        head = toRecycle.pop();
4023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        SegmentPool.INSTANCE.recycle(toRecycle);
4033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
4043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
4053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
4063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
4073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public OkBuffer write(ByteString byteString) {
4083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return write(byteString.data, 0, byteString.data.length);
4093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
4103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
4113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public OkBuffer writeUtf8(String string) {
412c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    // TODO: inline UTF-8 encoding to save allocating a byte[]?
4133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    byte[] data = string.getBytes(Util.UTF_8);
4143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return write(data, 0, data.length);
4153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
4163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
4173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public OkBuffer write(byte[] source) {
4183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return write(source, 0, source.length);
4193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
4203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
4213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public OkBuffer write(byte[] source, int offset, int byteCount) {
4223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int limit = offset + byteCount;
4233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    while (offset < limit) {
4243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      Segment tail = writableSegment(1);
4253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
4263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      int toCopy = Math.min(limit - offset, Segment.SIZE - tail.limit);
4273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      System.arraycopy(source, offset, tail.data, tail.limit, toCopy);
4283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
4293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      offset += toCopy;
4303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      tail.limit += toCopy;
4313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
4323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
4333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    this.size += byteCount;
4343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return this;
4353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
4363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
4373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public OkBuffer writeByte(int b) {
4383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment tail = writableSegment(1);
4393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    tail.data[tail.limit++] = (byte) b;
4403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    size += 1;
4413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return this;
4423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
4433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
4443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public OkBuffer writeShort(int s) {
4453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment tail = writableSegment(2);
4463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    byte[] data = tail.data;
4473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int limit = tail.limit;
448c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    data[limit++] = (byte) ((s >>> 8) & 0xff);
449c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    data[limit++] = (byte)  (s        & 0xff);
4503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    tail.limit = limit;
4513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    size += 2;
4523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return this;
4533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
4543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
455c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Override public BufferedSink writeShortLe(int s) {
456c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    return writeShort(Util.reverseBytesShort((short) s));
457c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  }
458c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
4593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public OkBuffer writeInt(int i) {
4603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment tail = writableSegment(4);
4613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    byte[] data = tail.data;
4623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int limit = tail.limit;
463c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    data[limit++] = (byte) ((i >>> 24) & 0xff);
464c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    data[limit++] = (byte) ((i >>> 16) & 0xff);
465c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    data[limit++] = (byte) ((i >>>  8) & 0xff);
466c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    data[limit++] = (byte)  (i         & 0xff);
4673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    tail.limit = limit;
4683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    size += 4;
4693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return this;
4703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
4713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
472c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Override public BufferedSink writeIntLe(int i) {
473c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    return writeInt(Util.reverseBytesInt(i));
474c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  }
475c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
476c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Override public OkBuffer writeLong(long v) {
477c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    Segment tail = writableSegment(8);
478c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    byte[] data = tail.data;
479c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    int limit = tail.limit;
480c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    data[limit++] = (byte) ((v >>> 56L) & 0xff);
481c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    data[limit++] = (byte) ((v >>> 48L) & 0xff);
482c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    data[limit++] = (byte) ((v >>> 40L) & 0xff);
483c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    data[limit++] = (byte) ((v >>> 32L) & 0xff);
484c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    data[limit++] = (byte) ((v >>> 24L) & 0xff);
485c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    data[limit++] = (byte) ((v >>> 16L) & 0xff);
486c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    data[limit++] = (byte) ((v >>>  8L) & 0xff);
487c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    data[limit++] = (byte)  (v          & 0xff);
488c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    tail.limit = limit;
489c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    size += 8;
490c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    return this;
491c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  }
492c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
493c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Override public BufferedSink writeLongLe(long v) {
494c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    return writeLong(reverseBytesLong(v));
495c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  }
496c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
4973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /**
4983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * Returns a tail segment that we can write at least {@code minimumCapacity}
4993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * bytes to, creating it if necessary.
5003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   */
5013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  Segment writableSegment(int minimumCapacity) {
5023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (minimumCapacity < 1 || minimumCapacity > Segment.SIZE) throw new IllegalArgumentException();
5033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
5043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (head == null) {
5053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      head = SegmentPool.INSTANCE.take(); // Acquire a first segment.
5063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return head.next = head.prev = head;
5073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
5083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
5093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment tail = head.prev;
5103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (tail.limit + minimumCapacity > Segment.SIZE) {
5113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      tail = tail.push(SegmentPool.INSTANCE.take()); // Append a new empty segment to fill up.
5123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
5133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return tail;
5143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
5153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
5163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public void write(OkBuffer source, long byteCount) {
5173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // Move bytes from the head of the source buffer to the tail of this buffer
5183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // while balancing two conflicting goals: don't waste CPU and don't waste
5193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // memory.
5203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // Don't waste CPU (ie. don't copy data around).
5233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // Copying large amounts of data is expensive. Instead, we prefer to
5253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // reassign entire segments from one OkBuffer to the other.
5263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // Don't waste memory.
5293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // As an invariant, adjacent pairs of segments in an OkBuffer should be at
5313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // least 50% full, except for the head segment and the tail segment.
5323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // The head segment cannot maintain the invariant because the application is
5343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // consuming bytes from this segment, decreasing its level.
5353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // The tail segment cannot maintain the invariant because the application is
5373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // producing bytes, which may require new nearly-empty tail segments to be
5383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // appended.
5393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // Moving segments between buffers
5423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // When writing one buffer to another, we prefer to reassign entire segments
5443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // over copying bytes into their most compact form. Suppose we have a buffer
5453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // with these segment levels [91%, 61%]. If we append a buffer with a
5463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // single [72%] segment, that yields [91%, 61%, 72%]. No bytes are copied.
5473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // Or suppose we have a buffer with these segment levels: [100%, 2%], and we
5493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // want to append it to a buffer with these segment levels [99%, 3%]. This
5503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // operation will yield the following segments: [100%, 2%, 99%, 3%]. That
5513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // is, we do not spend time copying bytes around to achieve more efficient
5523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // memory use like [100%, 100%, 4%].
5533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // When combining buffers, we will compact adjacent buffers when their
5553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // combined level doesn't exceed 100%. For example, when we start with
5563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // [100%, 40%] and append [30%, 80%], the result is [100%, 70%, 80%].
5573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // Splitting segments
5603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    //
5613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // Occasionally we write only part of a source buffer to a sink buffer. For
5623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // example, given a sink [51%, 91%], we may want to write the first 30% of
5633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // a source [92%, 82%] to it. To simplify, we first transform the source to
5643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // an equivalent buffer [30%, 62%, 82%] and then move the head segment,
5653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // yielding sink [51%, 91%, 30%] and source [62%, 82%].
5663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
5673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (source == this) {
5683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      throw new IllegalArgumentException("source == this");
5693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
5703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    checkOffsetAndCount(source.size, 0, byteCount);
5713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
5723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    while (byteCount > 0) {
5733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      // Is a prefix of the source's head segment all that we need to move?
5743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      if (byteCount < (source.head.limit - source.head.pos)) {
5753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        Segment tail = head != null ? head.prev : null;
5763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        if (tail == null || byteCount + (tail.limit - tail.pos) > Segment.SIZE) {
5773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          // We're going to need another segment. Split the source's head
5783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          // segment in two, then move the first of those two to this buffer.
5793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          source.head = source.head.split((int) byteCount);
5803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        } else {
5813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          // Our existing segments are sufficient. Move bytes from source's head to our tail.
5823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          source.head.writeTo(tail, (int) byteCount);
5833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          source.size -= byteCount;
5843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          this.size += byteCount;
5853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          return;
5863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        }
5873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
5883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
5893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      // Remove the source's head segment and append it to our tail.
5903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      Segment segmentToMove = source.head;
5913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      long movedByteCount = segmentToMove.limit - segmentToMove.pos;
5923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      source.head = segmentToMove.pop();
5933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      if (head == null) {
5943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        head = segmentToMove;
5953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        head.next = head.prev = head;
5963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      } else {
5973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        Segment tail = head.prev;
5983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        tail = tail.push(segmentToMove);
5993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        tail.compact();
6003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
6013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      source.size -= movedByteCount;
6023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      this.size += movedByteCount;
6033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      byteCount -= movedByteCount;
6043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
6053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
6063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
6073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public long read(OkBuffer sink, long byteCount) {
6083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (this.size == 0) return -1L;
6093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (byteCount > this.size) byteCount = this.size;
6103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    sink.write(this, byteCount);
6113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return byteCount;
6123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
6133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
6143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public OkBuffer deadline(Deadline deadline) {
6153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    // All operations are in memory so this class doesn't need to honor deadlines.
6163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return this;
6173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
6183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
619c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Override public long indexOf(byte b) {
6203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return indexOf(b, 0);
6213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
6223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
6233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /**
6243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * Returns the index of {@code b} in this at or beyond {@code fromIndex}, or
6253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * -1 if this buffer does not contain {@code b} in that range.
6263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   */
6273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public long indexOf(byte b, long fromIndex) {
6283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment s = head;
6293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (s == null) return -1L;
6303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    long offset = 0L;
6313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    do {
6323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      int segmentByteCount = s.limit - s.pos;
6333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      if (fromIndex > segmentByteCount) {
6343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        fromIndex -= segmentByteCount;
6353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      } else {
6363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        byte[] data = s.data;
6373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        for (long pos = s.pos + fromIndex, limit = s.limit; pos < limit; pos++) {
6383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          if (data[(int) pos] == b) return offset + pos - s.pos;
6393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        }
6403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        fromIndex = 0;
6413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
6423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      offset += segmentByteCount;
6433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      s = s.next;
6443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    } while (s != head);
6453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return -1L;
6463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
6473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
6483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public void flush() {
6493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
6503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
6513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public void close() {
6523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
6533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
6543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /** For testing. This returns the sizes of the segments in this buffer. */
6553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  List<Integer> segmentSizes() {
6563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (head == null) return Collections.emptyList();
6573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    List<Integer> result = new ArrayList<Integer>();
6583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    result.add(head.limit - head.pos);
6593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    for (Segment s = head.next; s != head; s = s.next) {
6603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      result.add(s.limit - s.pos);
6613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
6623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return result;
6633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
6643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
6653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public boolean equals(Object o) {
6663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (!(o instanceof OkBuffer)) return false;
6673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    OkBuffer that = (OkBuffer) o;
6683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (size != that.size) return false;
6693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (size == 0) return true; // Both buffers are empty.
6703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
6713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment sa = this.head;
6723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment sb = that.head;
6733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int posA = sa.pos;
6743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int posB = sb.pos;
6753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
6763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    for (long pos = 0, count; pos < size; pos += count) {
6773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      count = Math.min(sa.limit - posA, sb.limit - posB);
6783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
6793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      for (int i = 0; i < count; i++) {
6803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        if (sa.data[posA++] != sb.data[posB++]) return false;
6813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
6823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
6833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      if (posA == sa.limit) {
6843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        sa = sa.next;
6853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        posA = sa.pos;
6863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
6873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
6883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      if (posB == sb.limit) {
6893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        sb = sb.next;
6903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        posB = sb.pos;
6913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
6923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
6933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
6943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return true;
6953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
6963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
6973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public int hashCode() {
6983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Segment s = head;
6993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (s == null) return 0;
7003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    int result = 1;
7013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    do {
7023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      for (int pos = s.pos, limit = s.limit; pos < limit; pos++) {
7033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        result = 31 * result + s.data[pos];
7043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
7053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      s = s.next;
7063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    } while (s != head);
7073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return result;
7083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
7093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
7103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public String toString() {
7113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (size == 0) {
7123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return "OkBuffer[size=0]";
7133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
7143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
7153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (size <= 16) {
7163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      ByteString data = clone().readByteString(size);
7173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return String.format("OkBuffer[size=%s data=%s]", size, data.hex());
7183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
7193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
7203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    try {
7213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      MessageDigest md5 = MessageDigest.getInstance("MD5");
7223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      md5.update(head.data, head.pos, head.limit - head.pos);
7233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      for (Segment s = head.next; s != head; s = s.next) {
7243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        md5.update(s.data, s.pos, s.limit - s.pos);
7253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
7263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return String.format("OkBuffer[size=%s md5=%s]",
7273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          size, ByteString.of(md5.digest()).hex());
7283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    } catch (NoSuchAlgorithmException e) {
7293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      throw new AssertionError();
7303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
7313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
7323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
7333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /** Returns a deep copy of this buffer. */
7343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public OkBuffer clone() {
7353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    OkBuffer result = new OkBuffer();
7363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (size() == 0) return result;
7373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
7383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    result.write(head.data, head.pos, head.limit - head.pos);
7393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    for (Segment s = head.next; s != head; s = s.next) {
7403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      result.write(s.data, s.pos, s.limit - s.pos);
7413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
7423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
7433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return result;
7443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
7453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller}
746