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 (long pos = s.pos + fromIndex, limit = s.limit; pos < limit; pos++) { 1246 if (data[(int) 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 indexOfElement(ByteString targetBytes) { 1257 return indexOfElement(targetBytes, 0); 1258 } 1259 1260 @Override public long indexOfElement(ByteString targetBytes, long fromIndex) { 1261 if (fromIndex < 0) throw new IllegalArgumentException("fromIndex < 0"); 1262 1263 Segment s = head; 1264 if (s == null) return -1L; 1265 long offset = 0L; 1266 byte[] toFind = targetBytes.toByteArray(); 1267 do { 1268 int segmentByteCount = s.limit - s.pos; 1269 if (fromIndex >= segmentByteCount) { 1270 fromIndex -= segmentByteCount; 1271 } else { 1272 byte[] data = s.data; 1273 for (long pos = s.pos + fromIndex, limit = s.limit; pos < limit; pos++) { 1274 byte b = data[(int) pos]; 1275 for (byte targetByte : toFind) { 1276 if (b == targetByte) return offset + pos - s.pos; 1277 } 1278 } 1279 fromIndex = 0; 1280 } 1281 offset += segmentByteCount; 1282 s = s.next; 1283 } while (s != head); 1284 return -1L; 1285 } 1286 1287 @Override public void flush() { 1288 } 1289 1290 @Override public void close() { 1291 } 1292 1293 @Override public Timeout timeout() { 1294 return Timeout.NONE; 1295 } 1296 1297 /** For testing. This returns the sizes of the segments in this buffer. */ 1298 List<Integer> segmentSizes() { 1299 if (head == null) return Collections.emptyList(); 1300 List<Integer> result = new ArrayList<>(); 1301 result.add(head.limit - head.pos); 1302 for (Segment s = head.next; s != head; s = s.next) { 1303 result.add(s.limit - s.pos); 1304 } 1305 return result; 1306 } 1307 1308 @Override public boolean equals(Object o) { 1309 if (this == o) return true; 1310 if (!(o instanceof Buffer)) return false; 1311 Buffer that = (Buffer) o; 1312 if (size != that.size) return false; 1313 if (size == 0) return true; // Both buffers are empty. 1314 1315 Segment sa = this.head; 1316 Segment sb = that.head; 1317 int posA = sa.pos; 1318 int posB = sb.pos; 1319 1320 for (long pos = 0, count; pos < size; pos += count) { 1321 count = Math.min(sa.limit - posA, sb.limit - posB); 1322 1323 for (int i = 0; i < count; i++) { 1324 if (sa.data[posA++] != sb.data[posB++]) return false; 1325 } 1326 1327 if (posA == sa.limit) { 1328 sa = sa.next; 1329 posA = sa.pos; 1330 } 1331 1332 if (posB == sb.limit) { 1333 sb = sb.next; 1334 posB = sb.pos; 1335 } 1336 } 1337 1338 return true; 1339 } 1340 1341 @Override public int hashCode() { 1342 Segment s = head; 1343 if (s == null) return 0; 1344 int result = 1; 1345 do { 1346 for (int pos = s.pos, limit = s.limit; pos < limit; pos++) { 1347 result = 31 * result + s.data[pos]; 1348 } 1349 s = s.next; 1350 } while (s != head); 1351 return result; 1352 } 1353 1354 @Override public String toString() { 1355 if (size == 0) { 1356 return "Buffer[size=0]"; 1357 } 1358 1359 if (size <= 16) { 1360 ByteString data = clone().readByteString(); 1361 return String.format("Buffer[size=%s data=%s]", size, data.hex()); 1362 } 1363 1364 try { 1365 MessageDigest md5 = MessageDigest.getInstance("MD5"); 1366 md5.update(head.data, head.pos, head.limit - head.pos); 1367 for (Segment s = head.next; s != head; s = s.next) { 1368 md5.update(s.data, s.pos, s.limit - s.pos); 1369 } 1370 return String.format("Buffer[size=%s md5=%s]", 1371 size, ByteString.of(md5.digest()).hex()); 1372 } catch (NoSuchAlgorithmException e) { 1373 throw new AssertionError(); 1374 } 1375 } 1376 1377 /** Returns a deep copy of this buffer. */ 1378 @Override public Buffer clone() { 1379 Buffer result = new Buffer(); 1380 if (size == 0) return result; 1381 1382 result.head = new Segment(head); 1383 result.head.next = result.head.prev = result.head; 1384 for (Segment s = head.next; s != head; s = s.next) { 1385 result.head.prev.push(new Segment(s)); 1386 } 1387 result.size = size; 1388 return result; 1389 } 1390 1391 /** Returns an immutable copy of this buffer as a byte string. */ 1392 public ByteString snapshot() { 1393 if (size > Integer.MAX_VALUE) { 1394 throw new IllegalArgumentException("size > Integer.MAX_VALUE: " + size); 1395 } 1396 return snapshot((int) size); 1397 } 1398 1399 /** 1400 * Returns an immutable copy of the first {@code byteCount} bytes of this buffer as a byte string. 1401 */ 1402 public ByteString snapshot(int byteCount) { 1403 if (byteCount == 0) return ByteString.EMPTY; 1404 return new SegmentedByteString(this, byteCount); 1405 } 1406 } 1407