• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 Square, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package okio;
17 
18 import java.io.EOFException;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.OutputStream;
22 import java.nio.charset.Charset;
23 import java.security.MessageDigest;
24 import java.security.NoSuchAlgorithmException;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 
29 import static okio.Util.checkOffsetAndCount;
30 import static okio.Util.reverseBytesLong;
31 
32 /**
33  * A collection of bytes in memory.
34  *
35  * <p><strong>Moving data from one buffer to another is fast.</strong> Instead
36  * of copying bytes from one place in memory to another, this class just changes
37  * ownership of the underlying byte arrays.
38  *
39  * <p><strong>This buffer grows with your data.</strong> Just like ArrayList,
40  * each buffer starts small. It consumes only the memory it needs to.
41  *
42  * <p><strong>This buffer pools its byte arrays.</strong> When you allocate a
43  * byte array in Java, the runtime must zero-fill the requested array before
44  * returning it to you. Even if you're going to write over that space anyway.
45  * This class avoids zero-fill and GC churn by pooling byte arrays.
46  */
47 public final class Buffer implements BufferedSource, BufferedSink, Cloneable {
48   private static final byte[] DIGITS =
49       { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
50   static final int REPLACEMENT_CHARACTER = '\ufffd';
51 
52   Segment head;
53   long size;
54 
Buffer()55   public Buffer() {
56   }
57 
58   /** Returns the number of bytes currently in this buffer. */
size()59   public long size() {
60     return size;
61   }
62 
buffer()63   @Override public Buffer buffer() {
64     return this;
65   }
66 
outputStream()67   @Override public OutputStream outputStream() {
68     return new OutputStream() {
69       @Override public void write(int b) {
70         writeByte((byte) b);
71       }
72 
73       @Override public void write(byte[] data, int offset, int byteCount) {
74         Buffer.this.write(data, offset, byteCount);
75       }
76 
77       @Override public void flush() {
78       }
79 
80       @Override public void close() {
81       }
82 
83       @Override public String toString() {
84         return this + ".outputStream()";
85       }
86     };
87   }
88 
89   @Override public Buffer emitCompleteSegments() {
90     return this; // Nowhere to emit to!
91   }
92 
93   @Override public BufferedSink emit() {
94     return this; // Nowhere to emit to!
95   }
96 
97   @Override public boolean exhausted() {
98     return size == 0;
99   }
100 
101   @Override public void require(long byteCount) throws EOFException {
102     if (size < byteCount) throw new EOFException();
103   }
104 
105   @Override public boolean request(long byteCount) {
106     return size >= byteCount;
107   }
108 
109   @Override public InputStream inputStream() {
110     return new InputStream() {
111       @Override public int read() {
112         if (size > 0) return readByte() & 0xff;
113         return -1;
114       }
115 
116       @Override public int read(byte[] sink, int offset, int byteCount) {
117         return Buffer.this.read(sink, offset, byteCount);
118       }
119 
120       @Override public int available() {
121         return (int) Math.min(size, Integer.MAX_VALUE);
122       }
123 
124       @Override public void close() {
125       }
126 
127       @Override public String toString() {
128         return Buffer.this + ".inputStream()";
129       }
130     };
131   }
132 
133   /** Copy the contents of this to {@code out}. */
134   public Buffer copyTo(OutputStream out) throws IOException {
135     return copyTo(out, 0, size);
136   }
137 
138   /**
139    * Copy {@code byteCount} bytes from this, starting at {@code offset}, to
140    * {@code out}.
141    */
142   public Buffer copyTo(OutputStream out, long offset, long byteCount) throws IOException {
143     if (out == null) throw new IllegalArgumentException("out == null");
144     checkOffsetAndCount(size, offset, byteCount);
145     if (byteCount == 0) return this;
146 
147     // Skip segments that we aren't copying from.
148     Segment s = head;
149     for (; offset >= (s.limit - s.pos); s = s.next) {
150       offset -= (s.limit - s.pos);
151     }
152 
153     // Copy from one segment at a time.
154     for (; byteCount > 0; s = s.next) {
155       int pos = (int) (s.pos + offset);
156       int toCopy = (int) Math.min(s.limit - pos, byteCount);
157       out.write(s.data, pos, toCopy);
158       byteCount -= toCopy;
159       offset = 0;
160     }
161 
162     return this;
163   }
164 
165   /** Copy {@code byteCount} bytes from this, starting at {@code offset}, to {@code out}. */
166   public Buffer copyTo(Buffer out, long offset, long byteCount) {
167     if (out == null) throw new IllegalArgumentException("out == null");
168     checkOffsetAndCount(size, offset, byteCount);
169     if (byteCount == 0) return this;
170 
171     out.size += byteCount;
172 
173     // Skip segments that we aren't copying from.
174     Segment s = head;
175     for (; offset >= (s.limit - s.pos); s = s.next) {
176       offset -= (s.limit - s.pos);
177     }
178 
179     // Copy one segment at a time.
180     for (; byteCount > 0; s = s.next) {
181       Segment copy = new Segment(s);
182       copy.pos += offset;
183       copy.limit = Math.min(copy.pos + (int) byteCount, copy.limit);
184       if (out.head == null) {
185         out.head = copy.next = copy.prev = copy;
186       } else {
187         out.head.prev.push(copy);
188       }
189       byteCount -= copy.limit - copy.pos;
190       offset = 0;
191     }
192 
193     return this;
194   }
195 
196   /** Write the contents of this to {@code out}. */
197   public Buffer writeTo(OutputStream out) throws IOException {
198     return writeTo(out, size);
199   }
200 
201   /** Write {@code byteCount} bytes from this to {@code out}. */
202   public Buffer writeTo(OutputStream out, long byteCount) throws IOException {
203     if (out == null) throw new IllegalArgumentException("out == null");
204     checkOffsetAndCount(size, 0, byteCount);
205 
206     Segment s = head;
207     while (byteCount > 0) {
208       int toCopy = (int) Math.min(byteCount, s.limit - s.pos);
209       out.write(s.data, s.pos, toCopy);
210 
211       s.pos += toCopy;
212       size -= toCopy;
213       byteCount -= toCopy;
214 
215       if (s.pos == s.limit) {
216         Segment toRecycle = s;
217         head = s = toRecycle.pop();
218         SegmentPool.recycle(toRecycle);
219       }
220     }
221 
222     return this;
223   }
224 
225   /** Read and exhaust bytes from {@code in} to this. */
226   public Buffer readFrom(InputStream in) throws IOException {
227     readFrom(in, Long.MAX_VALUE, true);
228     return this;
229   }
230 
231   /** Read {@code byteCount} bytes from {@code in} to this. */
232   public Buffer readFrom(InputStream in, long byteCount) throws IOException {
233     if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount);
234     readFrom(in, byteCount, false);
235     return this;
236   }
237 
238   private void readFrom(InputStream in, long byteCount, boolean forever) throws IOException {
239     if (in == null) throw new IllegalArgumentException("in == null");
240     while (byteCount > 0 || forever) {
241       Segment tail = writableSegment(1);
242       int maxToCopy = (int) Math.min(byteCount, Segment.SIZE - tail.limit);
243       int bytesRead = in.read(tail.data, tail.limit, maxToCopy);
244       if (bytesRead == -1) {
245         if (forever) return;
246         throw new EOFException();
247       }
248       tail.limit += bytesRead;
249       size += bytesRead;
250       byteCount -= bytesRead;
251     }
252   }
253 
254   /**
255    * Returns the number of bytes in segments that are not writable. This is the
256    * number of bytes that can be flushed immediately to an underlying sink
257    * without harming throughput.
258    */
259   public long completeSegmentByteCount() {
260     long result = size;
261     if (result == 0) return 0;
262 
263     // Omit the tail if it's still writable.
264     Segment tail = head.prev;
265     if (tail.limit < Segment.SIZE && tail.owner) {
266       result -= tail.limit - tail.pos;
267     }
268 
269     return result;
270   }
271 
272   @Override public byte readByte() {
273     if (size == 0) throw new IllegalStateException("size == 0");
274 
275     Segment segment = head;
276     int pos = segment.pos;
277     int limit = segment.limit;
278 
279     byte[] data = segment.data;
280     byte b = data[pos++];
281     size -= 1;
282 
283     if (pos == limit) {
284       head = segment.pop();
285       SegmentPool.recycle(segment);
286     } else {
287       segment.pos = pos;
288     }
289 
290     return b;
291   }
292 
293   /** Returns the byte at {@code pos}. */
294   public byte getByte(long pos) {
295     checkOffsetAndCount(size, pos, 1);
296     for (Segment s = head; true; s = s.next) {
297       int segmentByteCount = s.limit - s.pos;
298       if (pos < segmentByteCount) return s.data[s.pos + (int) pos];
299       pos -= segmentByteCount;
300     }
301   }
302 
303   @Override public short readShort() {
304     if (size < 2) throw new IllegalStateException("size < 2: " + size);
305 
306     Segment segment = head;
307     int pos = segment.pos;
308     int limit = segment.limit;
309 
310     // If the short is split across multiple segments, delegate to readByte().
311     if (limit - pos < 2) {
312       int s = (readByte() & 0xff) << 8
313           |   (readByte() & 0xff);
314       return (short) s;
315     }
316 
317     byte[] data = segment.data;
318     int s = (data[pos++] & 0xff) << 8
319         |   (data[pos++] & 0xff);
320     size -= 2;
321 
322     if (pos == limit) {
323       head = segment.pop();
324       SegmentPool.recycle(segment);
325     } else {
326       segment.pos = pos;
327     }
328 
329     return (short) s;
330   }
331 
332   @Override public int readInt() {
333     if (size < 4) throw new IllegalStateException("size < 4: " + size);
334 
335     Segment segment = head;
336     int pos = segment.pos;
337     int limit = segment.limit;
338 
339     // If the int is split across multiple segments, delegate to readByte().
340     if (limit - pos < 4) {
341       return (readByte() & 0xff) << 24
342           |  (readByte() & 0xff) << 16
343           |  (readByte() & 0xff) <<  8
344           |  (readByte() & 0xff);
345     }
346 
347     byte[] data = segment.data;
348     int i = (data[pos++] & 0xff) << 24
349         |   (data[pos++] & 0xff) << 16
350         |   (data[pos++] & 0xff) <<  8
351         |   (data[pos++] & 0xff);
352     size -= 4;
353 
354     if (pos == limit) {
355       head = segment.pop();
356       SegmentPool.recycle(segment);
357     } else {
358       segment.pos = pos;
359     }
360 
361     return i;
362   }
363 
364   @Override public long readLong() {
365     if (size < 8) throw new IllegalStateException("size < 8: " + size);
366 
367     Segment segment = head;
368     int pos = segment.pos;
369     int limit = segment.limit;
370 
371     // If the long is split across multiple segments, delegate to readInt().
372     if (limit - pos < 8) {
373       return (readInt() & 0xffffffffL) << 32
374           |  (readInt() & 0xffffffffL);
375     }
376 
377     byte[] data = segment.data;
378     long v = (data[pos++] & 0xffL) << 56
379         |    (data[pos++] & 0xffL) << 48
380         |    (data[pos++] & 0xffL) << 40
381         |    (data[pos++] & 0xffL) << 32
382         |    (data[pos++] & 0xffL) << 24
383         |    (data[pos++] & 0xffL) << 16
384         |    (data[pos++] & 0xffL) <<  8
385         |    (data[pos++] & 0xffL);
386     size -= 8;
387 
388     if (pos == limit) {
389       head = segment.pop();
390       SegmentPool.recycle(segment);
391     } else {
392       segment.pos = pos;
393     }
394 
395     return v;
396   }
397 
398   @Override public short readShortLe() {
399     return Util.reverseBytesShort(readShort());
400   }
401 
402   @Override public int readIntLe() {
403     return Util.reverseBytesInt(readInt());
404   }
405 
406   @Override public long readLongLe() {
407     return Util.reverseBytesLong(readLong());
408   }
409 
410   @Override public long readDecimalLong() {
411     if (size == 0) throw new IllegalStateException("size == 0");
412 
413     // This value is always built negatively in order to accommodate Long.MIN_VALUE.
414     long value = 0;
415     int seen = 0;
416     boolean negative = false;
417     boolean done = false;
418 
419     long overflowZone = Long.MIN_VALUE / 10;
420     long overflowDigit = (Long.MIN_VALUE % 10) + 1;
421 
422     do {
423       Segment segment = head;
424 
425       byte[] data = segment.data;
426       int pos = segment.pos;
427       int limit = segment.limit;
428 
429       for (; pos < limit; pos++, seen++) {
430         byte b = data[pos];
431         if (b >= '0' && b <= '9') {
432           int digit = '0' - b;
433 
434           // Detect when the digit would cause an overflow.
435           if (value < overflowZone || value == overflowZone && digit < overflowDigit) {
436             Buffer buffer = new Buffer().writeDecimalLong(value).writeByte(b);
437             if (!negative) buffer.readByte(); // Skip negative sign.
438             throw new NumberFormatException("Number too large: " + buffer.readUtf8());
439           }
440           value *= 10;
441           value += digit;
442         } else if (b == '-' && seen == 0) {
443           negative = true;
444           overflowDigit -= 1;
445         } else {
446           if (seen == 0) {
447             throw new NumberFormatException(
448                 "Expected leading [0-9] or '-' character but was 0x" + Integer.toHexString(b));
449           }
450           // Set a flag to stop iteration. We still need to run through segment updating below.
451           done = true;
452           break;
453         }
454       }
455 
456       if (pos == limit) {
457         head = segment.pop();
458         SegmentPool.recycle(segment);
459       } else {
460         segment.pos = pos;
461       }
462     } while (!done && head != null);
463 
464     size -= seen;
465     return negative ? value : -value;
466   }
467 
468   @Override public long readHexadecimalUnsignedLong() {
469     if (size == 0) throw new IllegalStateException("size == 0");
470 
471     long value = 0;
472     int seen = 0;
473     boolean done = false;
474 
475     do {
476       Segment segment = head;
477 
478       byte[] data = segment.data;
479       int pos = segment.pos;
480       int limit = segment.limit;
481 
482       for (; pos < limit; pos++, seen++) {
483         int digit;
484 
485         byte b = data[pos];
486         if (b >= '0' && b <= '9') {
487           digit = b - '0';
488         } else if (b >= 'a' && b <= 'f') {
489           digit = b - 'a' + 10;
490         } else if (b >= 'A' && b <= 'F') {
491           digit = b - 'A' + 10; // We never write uppercase, but we support reading it.
492         } else {
493           if (seen == 0) {
494             throw new NumberFormatException(
495                 "Expected leading [0-9a-fA-F] character but was 0x" + Integer.toHexString(b));
496           }
497           // Set a flag to stop iteration. We still need to run through segment updating below.
498           done = true;
499           break;
500         }
501 
502         // Detect when the shift will overflow.
503         if ((value & 0xf000000000000000L) != 0) {
504           Buffer buffer = new Buffer().writeHexadecimalUnsignedLong(value).writeByte(b);
505           throw new NumberFormatException("Number too large: " + buffer.readUtf8());
506         }
507 
508         value <<= 4;
509         value |= digit;
510       }
511 
512       if (pos == limit) {
513         head = segment.pop();
514         SegmentPool.recycle(segment);
515       } else {
516         segment.pos = pos;
517       }
518     } while (!done && head != null);
519 
520     size -= seen;
521     return value;
522   }
523 
524   @Override public ByteString readByteString() {
525     return new ByteString(readByteArray());
526   }
527 
528   @Override public ByteString readByteString(long byteCount) throws EOFException {
529     return new ByteString(readByteArray(byteCount));
530   }
531 
532   @Override public void readFully(Buffer sink, long byteCount) throws EOFException {
533     if (size < byteCount) {
534       sink.write(this, size); // Exhaust ourselves.
535       throw new EOFException();
536     }
537     sink.write(this, byteCount);
538   }
539 
540   @Override public long readAll(Sink sink) throws IOException {
541     long byteCount = size;
542     if (byteCount > 0) {
543       sink.write(this, byteCount);
544     }
545     return byteCount;
546   }
547 
548   @Override public String readUtf8() {
549     try {
550       return readString(size, Util.UTF_8);
551     } catch (EOFException e) {
552       throw new AssertionError(e);
553     }
554   }
555 
556   @Override public String readUtf8(long byteCount) throws EOFException {
557     return readString(byteCount, Util.UTF_8);
558   }
559 
560   @Override public String readString(Charset charset) {
561     try {
562       return readString(size, charset);
563     } catch (EOFException e) {
564       throw new AssertionError(e);
565     }
566   }
567 
568   @Override public String readString(long byteCount, Charset charset) throws EOFException {
569     checkOffsetAndCount(size, 0, byteCount);
570     if (charset == null) throw new IllegalArgumentException("charset == null");
571     if (byteCount > Integer.MAX_VALUE) {
572       throw new IllegalArgumentException("byteCount > Integer.MAX_VALUE: " + byteCount);
573     }
574     if (byteCount == 0) return "";
575 
576     Segment s = head;
577     if (s.pos + byteCount > s.limit) {
578       // If the string spans multiple segments, delegate to readBytes().
579       return new String(readByteArray(byteCount), charset);
580     }
581 
582     String result = new String(s.data, s.pos, (int) byteCount, charset);
583     s.pos += byteCount;
584     size -= byteCount;
585 
586     if (s.pos == s.limit) {
587       head = s.pop();
588       SegmentPool.recycle(s);
589     }
590 
591     return result;
592   }
593 
594   @Override public String readUtf8Line() throws EOFException {
595     long newline = indexOf((byte) '\n');
596 
597     if (newline == -1) {
598       return size != 0 ? readUtf8(size) : null;
599     }
600 
601     return readUtf8Line(newline);
602   }
603 
604   @Override public String readUtf8LineStrict() throws EOFException {
605     long newline = indexOf((byte) '\n');
606     if (newline == -1) {
607       Buffer data = new Buffer();
608       copyTo(data, 0, Math.min(32, size));
609       throw new EOFException("\\n not found: size=" + size()
610           + " content=" + data.readByteString().hex() + "...");
611     }
612     return readUtf8Line(newline);
613   }
614 
615   String readUtf8Line(long newline) throws EOFException {
616     if (newline > 0 && getByte(newline - 1) == '\r') {
617       // Read everything until '\r\n', then skip the '\r\n'.
618       String result = readUtf8((newline - 1));
619       skip(2);
620       return result;
621 
622     } else {
623       // Read everything until '\n', then skip the '\n'.
624       String result = readUtf8(newline);
625       skip(1);
626       return result;
627     }
628   }
629 
630   @Override public int readUtf8CodePoint() throws EOFException {
631     if (size == 0) throw new EOFException();
632 
633     byte b0 = getByte(0);
634     int codePoint;
635     int byteCount;
636     int min;
637 
638     if ((b0 & 0x80) == 0) {
639       // 0xxxxxxx.
640       codePoint = b0 & 0x7f;
641       byteCount = 1; // 7 bits (ASCII).
642       min = 0x0;
643 
644     } else if ((b0 & 0xe0) == 0xc0) {
645       // 0x110xxxxx
646       codePoint = b0 & 0x1f;
647       byteCount = 2; // 11 bits (5 + 6).
648       min = 0x80;
649 
650     } else if ((b0 & 0xf0) == 0xe0) {
651       // 0x1110xxxx
652       codePoint = b0 & 0x0f;
653       byteCount = 3; // 16 bits (4 + 6 + 6).
654       min = 0x800;
655 
656     } else if ((b0 & 0xf8) == 0xf0) {
657       // 0x11110xxx
658       codePoint = b0 & 0x07;
659       byteCount = 4; // 21 bits (3 + 6 + 6 + 6).
660       min = 0x10000;
661 
662     } else {
663       // We expected the first byte of a code point but got something else.
664       skip(1);
665       return REPLACEMENT_CHARACTER;
666     }
667 
668     if (size < byteCount) {
669       throw new EOFException("size < " + byteCount + ": " + size
670           + " (to read code point prefixed 0x" + Integer.toHexString(b0) + ")");
671     }
672 
673     // Read the continuation bytes. If we encounter a non-continuation byte, the sequence consumed
674     // thus far is truncated and is decoded as the replacement character. That non-continuation byte
675     // is left in the stream for processing by the next call to readUtf8CodePoint().
676     for (int i = 1; i < byteCount; i++) {
677       byte b = getByte(i);
678       if ((b & 0xc0) == 0x80) {
679         // 0x10xxxxxx
680         codePoint <<= 6;
681         codePoint |= b & 0x3f;
682       } else {
683         skip(i);
684         return REPLACEMENT_CHARACTER;
685       }
686     }
687 
688     skip(byteCount);
689 
690     if (codePoint > 0x10ffff) {
691       return REPLACEMENT_CHARACTER; // Reject code points larger than the Unicode maximum.
692     }
693 
694     if (codePoint >= 0xd800 && codePoint <= 0xdfff) {
695       return REPLACEMENT_CHARACTER; // Reject partial surrogates.
696     }
697 
698     if (codePoint < min) {
699       return REPLACEMENT_CHARACTER; // Reject overlong code points.
700     }
701 
702     return codePoint;
703   }
704 
705   @Override public byte[] readByteArray() {
706     try {
707       return readByteArray(size);
708     } catch (EOFException e) {
709       throw new AssertionError(e);
710     }
711   }
712 
713   @Override public byte[] readByteArray(long byteCount) throws EOFException {
714     checkOffsetAndCount(size, 0, byteCount);
715     if (byteCount > Integer.MAX_VALUE) {
716       throw new IllegalArgumentException("byteCount > Integer.MAX_VALUE: " + byteCount);
717     }
718 
719     byte[] result = new byte[(int) byteCount];
720     readFully(result);
721     return result;
722   }
723 
724   @Override public int read(byte[] sink) {
725     return read(sink, 0, sink.length);
726   }
727 
728   @Override public void readFully(byte[] sink) throws EOFException {
729     int offset = 0;
730     while (offset < sink.length) {
731       int read = read(sink, offset, sink.length - offset);
732       if (read == -1) throw new EOFException();
733       offset += read;
734     }
735   }
736 
737   @Override public int read(byte[] sink, int offset, int byteCount) {
738     checkOffsetAndCount(sink.length, offset, byteCount);
739 
740     Segment s = head;
741     if (s == null) return -1;
742     int toCopy = Math.min(byteCount, s.limit - s.pos);
743     System.arraycopy(s.data, s.pos, sink, offset, toCopy);
744 
745     s.pos += toCopy;
746     size -= toCopy;
747 
748     if (s.pos == s.limit) {
749       head = s.pop();
750       SegmentPool.recycle(s);
751     }
752 
753     return toCopy;
754   }
755 
756   /**
757    * Discards all bytes in this buffer. Calling this method when you're done
758    * with a buffer will return its segments to the pool.
759    */
760   public void clear() {
761     try {
762       skip(size);
763     } catch (EOFException e) {
764       throw new AssertionError(e);
765     }
766   }
767 
768   /** Discards {@code byteCount} bytes from the head of this buffer. */
769   @Override public void skip(long byteCount) throws EOFException {
770     while (byteCount > 0) {
771       if (head == null) throw new EOFException();
772 
773       int toSkip = (int) Math.min(byteCount, head.limit - head.pos);
774       size -= toSkip;
775       byteCount -= toSkip;
776       head.pos += toSkip;
777 
778       if (head.pos == head.limit) {
779         Segment toRecycle = head;
780         head = toRecycle.pop();
781         SegmentPool.recycle(toRecycle);
782       }
783     }
784   }
785 
786   @Override public Buffer write(ByteString byteString) {
787     if (byteString == null) throw new IllegalArgumentException("byteString == null");
788     byteString.write(this);
789     return this;
790   }
791 
792   @Override public Buffer writeUtf8(String string) {
793     return writeUtf8(string, 0, string.length());
794   }
795 
796   @Override public Buffer writeUtf8(String string, int beginIndex, int endIndex) {
797     if (string == null) throw new IllegalArgumentException("string == null");
798     if (beginIndex < 0) throw new IllegalAccessError("beginIndex < 0: " + beginIndex);
799     if (endIndex < beginIndex) {
800       throw new IllegalArgumentException("endIndex < beginIndex: " + endIndex + " < " + beginIndex);
801     }
802     if (endIndex > string.length()) {
803       throw new IllegalArgumentException(
804           "endIndex > string.length: " + endIndex + " > " + string.length());
805     }
806 
807     // Transcode a UTF-16 Java String to UTF-8 bytes.
808     for (int i = beginIndex; i < endIndex;) {
809       int c = string.charAt(i);
810 
811       if (c < 0x80) {
812         Segment tail = writableSegment(1);
813         byte[] data = tail.data;
814         int segmentOffset = tail.limit - i;
815         int runLimit = Math.min(endIndex, Segment.SIZE - segmentOffset);
816 
817         // Emit a 7-bit character with 1 byte.
818         data[segmentOffset + i++] = (byte) c; // 0xxxxxxx
819 
820         // Fast-path contiguous runs of ASCII characters. This is ugly, but yields a ~4x performance
821         // improvement over independent calls to writeByte().
822         while (i < runLimit) {
823           c = string.charAt(i);
824           if (c >= 0x80) break;
825           data[segmentOffset + i++] = (byte) c; // 0xxxxxxx
826         }
827 
828         int runSize = i + segmentOffset - tail.limit; // Equivalent to i - (previous i).
829         tail.limit += runSize;
830         size += runSize;
831 
832       } else if (c < 0x800) {
833         // Emit a 11-bit character with 2 bytes.
834         writeByte(c >>  6        | 0xc0); // 110xxxxx
835         writeByte(c       & 0x3f | 0x80); // 10xxxxxx
836         i++;
837 
838       } else if (c < 0xd800 || c > 0xdfff) {
839         // Emit a 16-bit character with 3 bytes.
840         writeByte(c >> 12        | 0xe0); // 1110xxxx
841         writeByte(c >>  6 & 0x3f | 0x80); // 10xxxxxx
842         writeByte(c       & 0x3f | 0x80); // 10xxxxxx
843         i++;
844 
845       } else {
846         // c is a surrogate. Make sure it is a high surrogate & that its successor is a low
847         // surrogate. If not, the UTF-16 is invalid, in which case we emit a replacement character.
848         int low = i + 1 < endIndex ? string.charAt(i + 1) : 0;
849         if (c > 0xdbff || low < 0xdc00 || low > 0xdfff) {
850           writeByte('?');
851           i++;
852           continue;
853         }
854 
855         // UTF-16 high surrogate: 110110xxxxxxxxxx (10 bits)
856         // UTF-16 low surrogate:  110111yyyyyyyyyy (10 bits)
857         // Unicode code point:    00010000000000000000 + xxxxxxxxxxyyyyyyyyyy (21 bits)
858         int codePoint = 0x010000 + ((c & ~0xd800) << 10 | low & ~0xdc00);
859 
860         // Emit a 21-bit character with 4 bytes.
861         writeByte(codePoint >> 18        | 0xf0); // 11110xxx
862         writeByte(codePoint >> 12 & 0x3f | 0x80); // 10xxxxxx
863         writeByte(codePoint >>  6 & 0x3f | 0x80); // 10xxyyyy
864         writeByte(codePoint       & 0x3f | 0x80); // 10yyyyyy
865         i += 2;
866       }
867     }
868 
869     return this;
870   }
871 
872   @Override public Buffer writeUtf8CodePoint(int codePoint) {
873     if (codePoint < 0x80) {
874       // Emit a 7-bit code point with 1 byte.
875       writeByte(codePoint);
876 
877     } else if (codePoint < 0x800) {
878       // Emit a 11-bit code point with 2 bytes.
879       writeByte(codePoint >>  6        | 0xc0); // 110xxxxx
880       writeByte(codePoint       & 0x3f | 0x80); // 10xxxxxx
881 
882     } else if (codePoint < 0x10000) {
883       if (codePoint >= 0xd800 && codePoint <= 0xdfff) {
884         throw new IllegalArgumentException(
885             "Unexpected code point: " + Integer.toHexString(codePoint));
886       }
887 
888       // Emit a 16-bit code point with 3 bytes.
889       writeByte(codePoint >> 12        | 0xe0); // 1110xxxx
890       writeByte(codePoint >>  6 & 0x3f | 0x80); // 10xxxxxx
891       writeByte(codePoint       & 0x3f | 0x80); // 10xxxxxx
892 
893     } else if (codePoint <= 0x10ffff) {
894       // Emit a 21-bit code point with 4 bytes.
895       writeByte(codePoint >> 18        | 0xf0); // 11110xxx
896       writeByte(codePoint >> 12 & 0x3f | 0x80); // 10xxxxxx
897       writeByte(codePoint >>  6 & 0x3f | 0x80); // 10xxxxxx
898       writeByte(codePoint       & 0x3f | 0x80); // 10xxxxxx
899 
900     } else {
901       throw new IllegalArgumentException(
902           "Unexpected code point: " + Integer.toHexString(codePoint));
903     }
904 
905     return this;
906   }
907 
908   @Override public Buffer writeString(String string, Charset charset) {
909     return writeString(string, 0, string.length(), charset);
910   }
911 
912   @Override
913   public Buffer writeString(String string, int beginIndex, int endIndex, Charset charset) {
914     if (string == null) throw new IllegalArgumentException("string == null");
915     if (beginIndex < 0) throw new IllegalAccessError("beginIndex < 0: " + beginIndex);
916     if (endIndex < beginIndex) {
917       throw new IllegalArgumentException("endIndex < beginIndex: " + endIndex + " < " + beginIndex);
918     }
919     if (endIndex > string.length()) {
920       throw new IllegalArgumentException(
921           "endIndex > string.length: " + endIndex + " > " + string.length());
922     }
923     if (charset == null) throw new IllegalArgumentException("charset == null");
924     if (charset.equals(Util.UTF_8)) return writeUtf8(string);
925     byte[] data = string.substring(beginIndex, endIndex).getBytes(charset);
926     return write(data, 0, data.length);
927   }
928 
929   @Override public Buffer write(byte[] source) {
930     if (source == null) throw new IllegalArgumentException("source == null");
931     return write(source, 0, source.length);
932   }
933 
934   @Override public Buffer write(byte[] source, int offset, int byteCount) {
935     if (source == null) throw new IllegalArgumentException("source == null");
936     checkOffsetAndCount(source.length, offset, byteCount);
937 
938     int limit = offset + byteCount;
939     while (offset < limit) {
940       Segment tail = writableSegment(1);
941 
942       int toCopy = Math.min(limit - offset, Segment.SIZE - tail.limit);
943       System.arraycopy(source, offset, tail.data, tail.limit, toCopy);
944 
945       offset += toCopy;
946       tail.limit += toCopy;
947     }
948 
949     size += byteCount;
950     return this;
951   }
952 
953   @Override public long writeAll(Source source) throws IOException {
954     if (source == null) throw new IllegalArgumentException("source == null");
955     long totalBytesRead = 0;
956     for (long readCount; (readCount = source.read(this, Segment.SIZE)) != -1; ) {
957       totalBytesRead += readCount;
958     }
959     return totalBytesRead;
960   }
961 
962   @Override public BufferedSink write(Source source, long byteCount) throws IOException {
963     while (byteCount > 0) {
964       long read = source.read(this, byteCount);
965       if (read == -1) throw new EOFException();
966       byteCount -= read;
967     }
968     return this;
969   }
970 
971   @Override public Buffer writeByte(int b) {
972     Segment tail = writableSegment(1);
973     tail.data[tail.limit++] = (byte) b;
974     size += 1;
975     return this;
976   }
977 
978   @Override public Buffer writeShort(int s) {
979     Segment tail = writableSegment(2);
980     byte[] data = tail.data;
981     int limit = tail.limit;
982     data[limit++] = (byte) ((s >>> 8) & 0xff);
983     data[limit++] = (byte)  (s        & 0xff);
984     tail.limit = limit;
985     size += 2;
986     return this;
987   }
988 
989   @Override public Buffer writeShortLe(int s) {
990     return writeShort(Util.reverseBytesShort((short) s));
991   }
992 
993   @Override public Buffer writeInt(int i) {
994     Segment tail = writableSegment(4);
995     byte[] data = tail.data;
996     int limit = tail.limit;
997     data[limit++] = (byte) ((i >>> 24) & 0xff);
998     data[limit++] = (byte) ((i >>> 16) & 0xff);
999     data[limit++] = (byte) ((i >>>  8) & 0xff);
1000     data[limit++] = (byte)  (i         & 0xff);
1001     tail.limit = limit;
1002     size += 4;
1003     return this;
1004   }
1005 
1006   @Override public Buffer writeIntLe(int i) {
1007     return writeInt(Util.reverseBytesInt(i));
1008   }
1009 
1010   @Override public Buffer writeLong(long v) {
1011     Segment tail = writableSegment(8);
1012     byte[] data = tail.data;
1013     int limit = tail.limit;
1014     data[limit++] = (byte) ((v >>> 56L) & 0xff);
1015     data[limit++] = (byte) ((v >>> 48L) & 0xff);
1016     data[limit++] = (byte) ((v >>> 40L) & 0xff);
1017     data[limit++] = (byte) ((v >>> 32L) & 0xff);
1018     data[limit++] = (byte) ((v >>> 24L) & 0xff);
1019     data[limit++] = (byte) ((v >>> 16L) & 0xff);
1020     data[limit++] = (byte) ((v >>>  8L) & 0xff);
1021     data[limit++] = (byte)  (v          & 0xff);
1022     tail.limit = limit;
1023     size += 8;
1024     return this;
1025   }
1026 
1027   @Override public Buffer writeLongLe(long v) {
1028     return writeLong(reverseBytesLong(v));
1029   }
1030 
1031   @Override public Buffer writeDecimalLong(long v) {
1032     if (v == 0) {
1033       // Both a shortcut and required since the following code can't handle zero.
1034       return writeByte('0');
1035     }
1036 
1037     boolean negative = false;
1038     if (v < 0) {
1039       v = -v;
1040       if (v < 0) { // Only true for Long.MIN_VALUE.
1041         return writeUtf8("-9223372036854775808");
1042       }
1043       negative = true;
1044     }
1045 
1046     // Binary search for character width which favors matching lower numbers.
1047     int width = //
1048           v < 100000000L
1049         ? v < 10000L
1050         ? v < 100L
1051         ? v < 10L ? 1 : 2
1052         : v < 1000L ? 3 : 4
1053         : v < 1000000L
1054         ? v < 100000L ? 5 : 6
1055         : v < 10000000L ? 7 : 8
1056         : v < 1000000000000L
1057         ? v < 10000000000L
1058         ? v < 1000000000L ? 9 : 10
1059         : v < 100000000000L ? 11 : 12
1060         : v < 1000000000000000L
1061         ? v < 10000000000000L ? 13
1062         : v < 100000000000000L ? 14 : 15
1063         : v < 100000000000000000L
1064         ? v < 10000000000000000L ? 16 : 17
1065         : v < 1000000000000000000L ? 18 : 19;
1066     if (negative) {
1067       ++width;
1068     }
1069 
1070     Segment tail = writableSegment(width);
1071     byte[] data = tail.data;
1072     int pos = tail.limit + width; // We write backwards from right to left.
1073     while (v != 0) {
1074       int digit = (int) (v % 10);
1075       data[--pos] = DIGITS[digit];
1076       v /= 10;
1077     }
1078     if (negative) {
1079       data[--pos] = '-';
1080     }
1081 
1082     tail.limit += width;
1083     this.size += width;
1084     return this;
1085   }
1086 
1087   @Override public Buffer writeHexadecimalUnsignedLong(long v) {
1088     if (v == 0) {
1089       // Both a shortcut and required since the following code can't handle zero.
1090       return writeByte('0');
1091     }
1092 
1093     int width = Long.numberOfTrailingZeros(Long.highestOneBit(v)) / 4 + 1;
1094 
1095     Segment tail = writableSegment(width);
1096     byte[] data = tail.data;
1097     for (int pos = tail.limit + width - 1, start = tail.limit; pos >= start; pos--) {
1098       data[pos] = DIGITS[(int) (v & 0xF)];
1099       v >>>= 4;
1100     }
1101     tail.limit += width;
1102     size += width;
1103     return this;
1104   }
1105 
1106   /**
1107    * Returns a tail segment that we can write at least {@code minimumCapacity}
1108    * bytes to, creating it if necessary.
1109    */
1110   Segment writableSegment(int minimumCapacity) {
1111     if (minimumCapacity < 1 || minimumCapacity > Segment.SIZE) throw new IllegalArgumentException();
1112 
1113     if (head == null) {
1114       head = SegmentPool.take(); // Acquire a first segment.
1115       return head.next = head.prev = head;
1116     }
1117 
1118     Segment tail = head.prev;
1119     if (tail.limit + minimumCapacity > Segment.SIZE || !tail.owner) {
1120       tail = tail.push(SegmentPool.take()); // Append a new empty segment to fill up.
1121     }
1122     return tail;
1123   }
1124 
1125   @Override public void write(Buffer source, long byteCount) {
1126     // Move bytes from the head of the source buffer to the tail of this buffer
1127     // while balancing two conflicting goals: don't waste CPU and don't waste
1128     // memory.
1129     //
1130     //
1131     // Don't waste CPU (ie. don't copy data around).
1132     //
1133     // Copying large amounts of data is expensive. Instead, we prefer to
1134     // reassign entire segments from one buffer to the other.
1135     //
1136     //
1137     // Don't waste memory.
1138     //
1139     // As an invariant, adjacent pairs of segments in a buffer should be at
1140     // least 50% full, except for the head segment and the tail segment.
1141     //
1142     // The head segment cannot maintain the invariant because the application is
1143     // consuming bytes from this segment, decreasing its level.
1144     //
1145     // The tail segment cannot maintain the invariant because the application is
1146     // producing bytes, which may require new nearly-empty tail segments to be
1147     // appended.
1148     //
1149     //
1150     // Moving segments between buffers
1151     //
1152     // When writing one buffer to another, we prefer to reassign entire segments
1153     // over copying bytes into their most compact form. Suppose we have a buffer
1154     // with these segment levels [91%, 61%]. If we append a buffer with a
1155     // single [72%] segment, that yields [91%, 61%, 72%]. No bytes are copied.
1156     //
1157     // Or suppose we have a buffer with these segment levels: [100%, 2%], and we
1158     // want to append it to a buffer with these segment levels [99%, 3%]. This
1159     // operation will yield the following segments: [100%, 2%, 99%, 3%]. That
1160     // is, we do not spend time copying bytes around to achieve more efficient
1161     // memory use like [100%, 100%, 4%].
1162     //
1163     // When combining buffers, we will compact adjacent buffers when their
1164     // combined level doesn't exceed 100%. For example, when we start with
1165     // [100%, 40%] and append [30%, 80%], the result is [100%, 70%, 80%].
1166     //
1167     //
1168     // Splitting segments
1169     //
1170     // Occasionally we write only part of a source buffer to a sink buffer. For
1171     // example, given a sink [51%, 91%], we may want to write the first 30% of
1172     // a source [92%, 82%] to it. To simplify, we first transform the source to
1173     // an equivalent buffer [30%, 62%, 82%] and then move the head segment,
1174     // yielding sink [51%, 91%, 30%] and source [62%, 82%].
1175 
1176     if (source == null) throw new IllegalArgumentException("source == null");
1177     if (source == this) throw new IllegalArgumentException("source == this");
1178     checkOffsetAndCount(source.size, 0, byteCount);
1179 
1180     while (byteCount > 0) {
1181       // Is a prefix of the source's head segment all that we need to move?
1182       if (byteCount < (source.head.limit - source.head.pos)) {
1183         Segment tail = head != null ? head.prev : null;
1184         if (tail != null && tail.owner
1185             && (byteCount + tail.limit - (tail.shared ? 0 : tail.pos) <= Segment.SIZE)) {
1186           // Our existing segments are sufficient. Move bytes from source's head to our tail.
1187           source.head.writeTo(tail, (int) byteCount);
1188           source.size -= byteCount;
1189           size += byteCount;
1190           return;
1191         } else {
1192           // We're going to need another segment. Split the source's head
1193           // segment in two, then move the first of those two to this buffer.
1194           source.head = source.head.split((int) byteCount);
1195         }
1196       }
1197 
1198       // Remove the source's head segment and append it to our tail.
1199       Segment segmentToMove = source.head;
1200       long movedByteCount = segmentToMove.limit - segmentToMove.pos;
1201       source.head = segmentToMove.pop();
1202       if (head == null) {
1203         head = segmentToMove;
1204         head.next = head.prev = head;
1205       } else {
1206         Segment tail = head.prev;
1207         tail = tail.push(segmentToMove);
1208         tail.compact();
1209       }
1210       source.size -= movedByteCount;
1211       size += movedByteCount;
1212       byteCount -= movedByteCount;
1213     }
1214   }
1215 
1216   @Override public long read(Buffer sink, long byteCount) {
1217     if (sink == null) throw new IllegalArgumentException("sink == null");
1218     if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount);
1219     if (size == 0) return -1L;
1220     if (byteCount > size) byteCount = size;
1221     sink.write(this, byteCount);
1222     return byteCount;
1223   }
1224 
1225   @Override public long indexOf(byte b) {
1226     return indexOf(b, 0);
1227   }
1228 
1229   /**
1230    * Returns the index of {@code b} in this at or beyond {@code fromIndex}, or
1231    * -1 if this buffer does not contain {@code b} in that range.
1232    */
1233   @Override public long indexOf(byte b, long fromIndex) {
1234     if (fromIndex < 0) throw new IllegalArgumentException("fromIndex < 0");
1235 
1236     Segment s = head;
1237     if (s == null) return -1L;
1238     long offset = 0L;
1239     do {
1240       int segmentByteCount = s.limit - s.pos;
1241       if (fromIndex >= segmentByteCount) {
1242         fromIndex -= segmentByteCount;
1243       } else {
1244         byte[] data = s.data;
1245         for (int pos = (int) (s.pos + fromIndex), limit = s.limit; pos < limit; pos++) {
1246           if (data[pos] == b) return offset + pos - s.pos;
1247         }
1248         fromIndex = 0;
1249       }
1250       offset += segmentByteCount;
1251       s = s.next;
1252     } while (s != head);
1253     return -1L;
1254   }
1255 
1256   @Override public long indexOf(ByteString bytes) throws IOException {
1257     return indexOf(bytes, 0);
1258   }
1259 
1260   @Override public long indexOf(ByteString bytes, long fromIndex) throws IOException {
1261     if (bytes.size() == 0) throw new IllegalArgumentException("bytes is empty");
1262     while (true) {
1263       fromIndex = indexOf(bytes.getByte(0), fromIndex);
1264       if (fromIndex == -1) {
1265         return -1;
1266       }
1267       if (rangeEquals(fromIndex, bytes)) {
1268         return fromIndex;
1269       }
1270       fromIndex++;
1271     }
1272   }
1273 
1274   @Override public long indexOfElement(ByteString targetBytes) {
1275     return indexOfElement(targetBytes, 0);
1276   }
1277 
1278   @Override public long indexOfElement(ByteString targetBytes, long fromIndex) {
1279     if (fromIndex < 0) throw new IllegalArgumentException("fromIndex < 0");
1280 
1281     Segment s = head;
1282     if (s == null) return -1L;
1283     long offset = 0L;
1284     byte[] toFind = targetBytes.toByteArray();
1285     do {
1286       int segmentByteCount = s.limit - s.pos;
1287       if (fromIndex >= segmentByteCount) {
1288         fromIndex -= segmentByteCount;
1289       } else {
1290         byte[] data = s.data;
1291         for (long pos = s.pos + fromIndex, limit = s.limit; pos < limit; pos++) {
1292           byte b = data[(int) pos];
1293           for (byte targetByte : toFind) {
1294             if (b == targetByte) return offset + pos - s.pos;
1295           }
1296         }
1297         fromIndex = 0;
1298       }
1299       offset += segmentByteCount;
1300       s = s.next;
1301     } while (s != head);
1302     return -1L;
1303   }
1304 
1305   boolean rangeEquals(long offset, ByteString bytes) {
1306     int byteCount = bytes.size();
1307     if (size - offset < byteCount) {
1308       return false;
1309     }
1310     for (int i = 0; i < byteCount; i++) {
1311       if (getByte(offset + i) != bytes.getByte(i)) {
1312         return false;
1313       }
1314     }
1315     return true;
1316   }
1317 
1318   @Override public void flush() {
1319   }
1320 
1321   @Override public void close() {
1322   }
1323 
1324   @Override public Timeout timeout() {
1325     return Timeout.NONE;
1326   }
1327 
1328   /** For testing. This returns the sizes of the segments in this buffer. */
1329   List<Integer> segmentSizes() {
1330     if (head == null) return Collections.emptyList();
1331     List<Integer> result = new ArrayList<>();
1332     result.add(head.limit - head.pos);
1333     for (Segment s = head.next; s != head; s = s.next) {
1334       result.add(s.limit - s.pos);
1335     }
1336     return result;
1337   }
1338 
1339   @Override public boolean equals(Object o) {
1340     if (this == o) return true;
1341     if (!(o instanceof Buffer)) return false;
1342     Buffer that = (Buffer) o;
1343     if (size != that.size) return false;
1344     if (size == 0) return true; // Both buffers are empty.
1345 
1346     Segment sa = this.head;
1347     Segment sb = that.head;
1348     int posA = sa.pos;
1349     int posB = sb.pos;
1350 
1351     for (long pos = 0, count; pos < size; pos += count) {
1352       count = Math.min(sa.limit - posA, sb.limit - posB);
1353 
1354       for (int i = 0; i < count; i++) {
1355         if (sa.data[posA++] != sb.data[posB++]) return false;
1356       }
1357 
1358       if (posA == sa.limit) {
1359         sa = sa.next;
1360         posA = sa.pos;
1361       }
1362 
1363       if (posB == sb.limit) {
1364         sb = sb.next;
1365         posB = sb.pos;
1366       }
1367     }
1368 
1369     return true;
1370   }
1371 
1372   @Override public int hashCode() {
1373     Segment s = head;
1374     if (s == null) return 0;
1375     int result = 1;
1376     do {
1377       for (int pos = s.pos, limit = s.limit; pos < limit; pos++) {
1378         result = 31 * result + s.data[pos];
1379       }
1380       s = s.next;
1381     } while (s != head);
1382     return result;
1383   }
1384 
1385   @Override public String toString() {
1386     if (size == 0) {
1387       return "Buffer[size=0]";
1388     }
1389 
1390     if (size <= 16) {
1391       ByteString data = clone().readByteString();
1392       return String.format("Buffer[size=%s data=%s]", size, data.hex());
1393     }
1394 
1395     try {
1396       MessageDigest md5 = MessageDigest.getInstance("MD5");
1397       md5.update(head.data, head.pos, head.limit - head.pos);
1398       for (Segment s = head.next; s != head; s = s.next) {
1399         md5.update(s.data, s.pos, s.limit - s.pos);
1400       }
1401       return String.format("Buffer[size=%s md5=%s]",
1402           size, ByteString.of(md5.digest()).hex());
1403     } catch (NoSuchAlgorithmException e) {
1404       throw new AssertionError();
1405     }
1406   }
1407 
1408   /** Returns a deep copy of this buffer. */
1409   @Override public Buffer clone() {
1410     Buffer result = new Buffer();
1411     if (size == 0) return result;
1412 
1413     result.head = new Segment(head);
1414     result.head.next = result.head.prev = result.head;
1415     for (Segment s = head.next; s != head; s = s.next) {
1416       result.head.prev.push(new Segment(s));
1417     }
1418     result.size = size;
1419     return result;
1420   }
1421 
1422   /** Returns an immutable copy of this buffer as a byte string. */
1423   public ByteString snapshot() {
1424     if (size > Integer.MAX_VALUE) {
1425       throw new IllegalArgumentException("size > Integer.MAX_VALUE: " + size);
1426     }
1427     return snapshot((int) size);
1428   }
1429 
1430   /**
1431    * Returns an immutable copy of the first {@code byteCount} bytes of this buffer as a byte string.
1432    */
1433   public ByteString snapshot(int byteCount) {
1434     if (byteCount == 0) return ByteString.EMPTY;
1435     return new SegmentedByteString(this, byteCount);
1436   }
1437 }
1438