1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 package com.google.protobuf; 32 33 import java.io.ByteArrayInputStream; 34 import java.io.ByteArrayOutputStream; 35 import java.io.IOException; 36 import java.io.InputStream; 37 import java.io.InvalidObjectException; 38 import java.io.ObjectInputStream; 39 import java.io.OutputStream; 40 import java.io.Serializable; 41 import java.io.UnsupportedEncodingException; 42 import java.nio.ByteBuffer; 43 import java.nio.charset.Charset; 44 import java.nio.charset.UnsupportedCharsetException; 45 import java.util.ArrayList; 46 import java.util.Arrays; 47 import java.util.Collection; 48 import java.util.Collections; 49 import java.util.Iterator; 50 import java.util.List; 51 import java.util.NoSuchElementException; 52 53 /** 54 * Immutable sequence of bytes. Substring is supported by sharing the reference 55 * to the immutable underlying bytes, as with {@link String}. Concatenation is 56 * likewise supported without copying (long strings) by building a tree of 57 * pieces in {@link RopeByteString}. 58 * <p> 59 * Like {@link String}, the contents of a {@link ByteString} can never be 60 * observed to change, not even in the presence of a data race or incorrect 61 * API usage in the client code. 62 * 63 * @author crazybob@google.com Bob Lee 64 * @author kenton@google.com Kenton Varda 65 * @author carlanton@google.com Carl Haverl 66 * @author martinrb@google.com Martin Buchholz 67 */ 68 public abstract class ByteString implements Iterable<Byte>, Serializable { 69 70 /** 71 * When two strings to be concatenated have a combined length shorter than 72 * this, we just copy their bytes on {@link #concat(ByteString)}. 73 * The trade-off is copy size versus the overhead of creating tree nodes 74 * in {@link RopeByteString}. 75 */ 76 static final int CONCATENATE_BY_COPY_SIZE = 128; 77 78 /** 79 * When copying an InputStream into a ByteString with .readFrom(), 80 * the chunks in the underlying rope start at 256 bytes, but double 81 * each iteration up to 8192 bytes. 82 */ 83 static final int MIN_READ_FROM_CHUNK_SIZE = 0x100; // 256b 84 static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000; // 8k 85 86 /** 87 * Empty {@code ByteString}. 88 */ 89 public static final ByteString EMPTY = new LiteralByteString(Internal.EMPTY_BYTE_ARRAY); 90 91 /** 92 * An interface to efficiently copy {@code byte[]}. 93 * 94 * <p>One of the noticeable costs of copying a byte[] into a new array using 95 * {@code System.arraycopy} is nullification of a new buffer before the copy. It has been shown 96 * the Hotspot VM is capable to intrisicfy {@code Arrays.copyOfRange} operation to avoid this 97 * expensive nullification and provide substantial performance gain. Unfortunately this does not 98 * hold on Android runtimes and could make the copy slightly slower due to additional code in 99 * the {@code Arrays.copyOfRange}. Thus we provide two different implementation for array copier 100 * for Hotspot and Android runtimes. 101 */ 102 private interface ByteArrayCopier { 103 /** 104 * Copies the specified range of the specified array into a new array 105 */ copyFrom(byte[] bytes, int offset, int size)106 byte[] copyFrom(byte[] bytes, int offset, int size); 107 } 108 109 /** Implementation of {@code ByteArrayCopier} which uses {@link System#arraycopy}. */ 110 private static final class SystemByteArrayCopier implements ByteArrayCopier { 111 @Override copyFrom(byte[] bytes, int offset, int size)112 public byte[] copyFrom(byte[] bytes, int offset, int size) { 113 byte[] copy = new byte[size]; 114 System.arraycopy(bytes, offset, copy, 0, size); 115 return copy; 116 } 117 } 118 119 /** Implementation of {@code ByteArrayCopier} which uses {@link Arrays#copyOfRange}. */ 120 private static final class ArraysByteArrayCopier implements ByteArrayCopier { 121 @Override copyFrom(byte[] bytes, int offset, int size)122 public byte[] copyFrom(byte[] bytes, int offset, int size) { 123 return Arrays.copyOfRange(bytes, offset, offset + size); 124 } 125 } 126 127 private static final ByteArrayCopier byteArrayCopier; 128 static { 129 boolean isAndroid = true; 130 try { 131 Class.forName("android.content.Context"); 132 } catch (ClassNotFoundException e) { 133 isAndroid = false; 134 } 135 136 byteArrayCopier = isAndroid ? new SystemByteArrayCopier() : new ArraysByteArrayCopier(); 137 } 138 139 /** 140 * Cached hash value. Intentionally accessed via a data race, which 141 * is safe because of the Java Memory Model's "no out-of-thin-air values" 142 * guarantees for ints. A value of 0 implies that the hash has not been set. 143 */ 144 private int hash = 0; 145 146 // This constructor is here to prevent subclassing outside of this package, ByteString()147 ByteString() {} 148 149 /** 150 * Gets the byte at the given index. This method should be used only for 151 * random access to individual bytes. To access bytes sequentially, use the 152 * {@link ByteIterator} returned by {@link #iterator()}, and call {@link 153 * #substring(int, int)} first if necessary. 154 * 155 * @param index index of byte 156 * @return the value 157 * @throws IndexOutOfBoundsException {@code index < 0 or index >= size} 158 */ byteAt(int index)159 public abstract byte byteAt(int index); 160 161 /** 162 * Return a {@link ByteString.ByteIterator} over the bytes in the ByteString. 163 * To avoid auto-boxing, you may get the iterator manually and call 164 * {@link ByteIterator#nextByte()}. 165 * 166 * @return the iterator 167 */ 168 @Override iterator()169 public final ByteIterator iterator() { 170 return new ByteIterator() { 171 private int position = 0; 172 private final int limit = size(); 173 174 @Override 175 public boolean hasNext() { 176 return position < limit; 177 } 178 179 @Override 180 public Byte next() { 181 // Boxing calls Byte.valueOf(byte), which does not instantiate. 182 return nextByte(); 183 } 184 185 @Override 186 public byte nextByte() { 187 try { 188 return byteAt(position++); 189 } catch (IndexOutOfBoundsException e) { 190 throw new NoSuchElementException(e.getMessage()); 191 } 192 } 193 194 @Override 195 public void remove() { 196 throw new UnsupportedOperationException(); 197 } 198 }; 199 } 200 201 /** 202 * This interface extends {@code Iterator<Byte>}, so that we can return an 203 * unboxed {@code byte}. 204 */ 205 public interface ByteIterator extends Iterator<Byte> { 206 /** 207 * An alternative to {@link Iterator#next()} that returns an 208 * unboxed primitive {@code byte}. 209 * 210 * @return the next {@code byte} in the iteration 211 * @throws NoSuchElementException if the iteration has no more elements 212 */ nextByte()213 byte nextByte(); 214 } 215 216 /** 217 * Gets the number of bytes. 218 * 219 * @return size in bytes 220 */ size()221 public abstract int size(); 222 223 /** 224 * Returns {@code true} if the size is {@code 0}, {@code false} otherwise. 225 * 226 * @return true if this is zero bytes long 227 */ isEmpty()228 public final boolean isEmpty() { 229 return size() == 0; 230 } 231 232 // ================================================================= 233 // ByteString -> substring 234 235 /** 236 * Return the substring from {@code beginIndex}, inclusive, to the end of the 237 * string. 238 * 239 * @param beginIndex start at this index 240 * @return substring sharing underlying data 241 * @throws IndexOutOfBoundsException if {@code beginIndex < 0} or 242 * {@code beginIndex > size()}. 243 */ substring(int beginIndex)244 public final ByteString substring(int beginIndex) { 245 return substring(beginIndex, size()); 246 } 247 248 /** 249 * Return the substring from {@code beginIndex}, inclusive, to {@code 250 * endIndex}, exclusive. 251 * 252 * @param beginIndex start at this index 253 * @param endIndex the last character is the one before this index 254 * @return substring sharing underlying data 255 * @throws IndexOutOfBoundsException if {@code beginIndex < 0}, 256 * {@code endIndex > size()}, or {@code beginIndex > endIndex}. 257 */ substring(int beginIndex, int endIndex)258 public abstract ByteString substring(int beginIndex, int endIndex); 259 260 /** 261 * Tests if this bytestring starts with the specified prefix. 262 * Similar to {@link String#startsWith(String)} 263 * 264 * @param prefix the prefix. 265 * @return <code>true</code> if the byte sequence represented by the 266 * argument is a prefix of the byte sequence represented by 267 * this string; <code>false</code> otherwise. 268 */ startsWith(ByteString prefix)269 public final boolean startsWith(ByteString prefix) { 270 return size() >= prefix.size() && 271 substring(0, prefix.size()).equals(prefix); 272 } 273 274 /** 275 * Tests if this bytestring ends with the specified suffix. 276 * Similar to {@link String#endsWith(String)} 277 * 278 * @param suffix the suffix. 279 * @return <code>true</code> if the byte sequence represented by the 280 * argument is a suffix of the byte sequence represented by 281 * this string; <code>false</code> otherwise. 282 */ endsWith(ByteString suffix)283 public final boolean endsWith(ByteString suffix) { 284 return size() >= suffix.size() && 285 substring(size() - suffix.size()).equals(suffix); 286 } 287 288 // ================================================================= 289 // byte[] -> ByteString 290 291 /** 292 * Copies the given bytes into a {@code ByteString}. 293 * 294 * @param bytes source array 295 * @param offset offset in source array 296 * @param size number of bytes to copy 297 * @return new {@code ByteString} 298 */ copyFrom(byte[] bytes, int offset, int size)299 public static ByteString copyFrom(byte[] bytes, int offset, int size) { 300 return new LiteralByteString(byteArrayCopier.copyFrom(bytes, offset, size)); 301 } 302 303 /** 304 * Copies the given bytes into a {@code ByteString}. 305 * 306 * @param bytes to copy 307 * @return new {@code ByteString} 308 */ copyFrom(byte[] bytes)309 public static ByteString copyFrom(byte[] bytes) { 310 return copyFrom(bytes, 0, bytes.length); 311 } 312 313 /** 314 * Wraps the given bytes into a {@code ByteString}. Intended for internal only 315 * usage to force a classload of ByteString before LiteralByteString. 316 */ wrap(byte[] bytes)317 static ByteString wrap(byte[] bytes) { 318 // TODO(dweis): Return EMPTY when bytes are empty to reduce allocations? 319 return new LiteralByteString(bytes); 320 } 321 322 /** 323 * Wraps the given bytes into a {@code ByteString}. Intended for internal only 324 * usage to force a classload of ByteString before BoundedByteString and 325 * LiteralByteString. 326 */ wrap(byte[] bytes, int offset, int length)327 static ByteString wrap(byte[] bytes, int offset, int length) { 328 return new BoundedByteString(bytes, offset, length); 329 } 330 331 /** 332 * Copies the next {@code size} bytes from a {@code java.nio.ByteBuffer} into 333 * a {@code ByteString}. 334 * 335 * @param bytes source buffer 336 * @param size number of bytes to copy 337 * @return new {@code ByteString} 338 */ copyFrom(ByteBuffer bytes, int size)339 public static ByteString copyFrom(ByteBuffer bytes, int size) { 340 byte[] copy = new byte[size]; 341 bytes.get(copy); 342 return new LiteralByteString(copy); 343 } 344 345 /** 346 * Copies the remaining bytes from a {@code java.nio.ByteBuffer} into 347 * a {@code ByteString}. 348 * 349 * @param bytes sourceBuffer 350 * @return new {@code ByteString} 351 */ copyFrom(ByteBuffer bytes)352 public static ByteString copyFrom(ByteBuffer bytes) { 353 return copyFrom(bytes, bytes.remaining()); 354 } 355 356 /** 357 * Encodes {@code text} into a sequence of bytes using the named charset 358 * and returns the result as a {@code ByteString}. 359 * 360 * @param text source string 361 * @param charsetName encoding to use 362 * @return new {@code ByteString} 363 * @throws UnsupportedEncodingException if the encoding isn't found 364 */ copyFrom(String text, String charsetName)365 public static ByteString copyFrom(String text, String charsetName) 366 throws UnsupportedEncodingException { 367 return new LiteralByteString(text.getBytes(charsetName)); 368 } 369 370 /** 371 * Encodes {@code text} into a sequence of bytes using the named charset 372 * and returns the result as a {@code ByteString}. 373 * 374 * @param text source string 375 * @param charset encode using this charset 376 * @return new {@code ByteString} 377 */ copyFrom(String text, Charset charset)378 public static ByteString copyFrom(String text, Charset charset) { 379 return new LiteralByteString(text.getBytes(charset)); 380 } 381 382 /** 383 * Encodes {@code text} into a sequence of UTF-8 bytes and returns the 384 * result as a {@code ByteString}. 385 * 386 * @param text source string 387 * @return new {@code ByteString} 388 */ copyFromUtf8(String text)389 public static ByteString copyFromUtf8(String text) { 390 return new LiteralByteString(text.getBytes(Internal.UTF_8)); 391 } 392 393 // ================================================================= 394 // InputStream -> ByteString 395 396 /** 397 * Completely reads the given stream's bytes into a 398 * {@code ByteString}, blocking if necessary until all bytes are 399 * read through to the end of the stream. 400 * 401 * <b>Performance notes:</b> The returned {@code ByteString} is an 402 * immutable tree of byte arrays ("chunks") of the stream data. The 403 * first chunk is small, with subsequent chunks each being double 404 * the size, up to 8K. 405 * 406 * <p>Each byte read from the input stream will be copied twice to ensure 407 * that the resulting ByteString is truly immutable. 408 * 409 * @param streamToDrain The source stream, which is read completely 410 * but not closed. 411 * @return A new {@code ByteString} which is made up of chunks of 412 * various sizes, depending on the behavior of the underlying 413 * stream. 414 * @throws IOException IOException is thrown if there is a problem 415 * reading the underlying stream. 416 */ readFrom(InputStream streamToDrain)417 public static ByteString readFrom(InputStream streamToDrain) 418 throws IOException { 419 return readFrom(streamToDrain, MIN_READ_FROM_CHUNK_SIZE, MAX_READ_FROM_CHUNK_SIZE); 420 } 421 422 /** 423 * Completely reads the given stream's bytes into a 424 * {@code ByteString}, blocking if necessary until all bytes are 425 * read through to the end of the stream. 426 * 427 * <b>Performance notes:</b> The returned {@code ByteString} is an 428 * immutable tree of byte arrays ("chunks") of the stream data. The 429 * chunkSize parameter sets the size of these byte arrays. 430 * 431 * <p>Each byte read from the input stream will be copied twice to ensure 432 * that the resulting ByteString is truly immutable. 433 * 434 * @param streamToDrain The source stream, which is read completely 435 * but not closed. 436 * @param chunkSize The size of the chunks in which to read the 437 * stream. 438 * @return A new {@code ByteString} which is made up of chunks of 439 * the given size. 440 * @throws IOException IOException is thrown if there is a problem 441 * reading the underlying stream. 442 */ readFrom(InputStream streamToDrain, int chunkSize)443 public static ByteString readFrom(InputStream streamToDrain, int chunkSize) 444 throws IOException { 445 return readFrom(streamToDrain, chunkSize, chunkSize); 446 } 447 448 // Helper method that takes the chunk size range as a parameter. readFrom(InputStream streamToDrain, int minChunkSize, int maxChunkSize)449 public static ByteString readFrom(InputStream streamToDrain, int minChunkSize, 450 int maxChunkSize) throws IOException { 451 Collection<ByteString> results = new ArrayList<ByteString>(); 452 453 // copy the inbound bytes into a list of chunks; the chunk size 454 // grows exponentially to support both short and long streams. 455 int chunkSize = minChunkSize; 456 while (true) { 457 ByteString chunk = readChunk(streamToDrain, chunkSize); 458 if (chunk == null) { 459 break; 460 } 461 results.add(chunk); 462 chunkSize = Math.min(chunkSize * 2, maxChunkSize); 463 } 464 465 return ByteString.copyFrom(results); 466 } 467 468 /** 469 * Blocks until a chunk of the given size can be made from the 470 * stream, or EOF is reached. Calls read() repeatedly in case the 471 * given stream implementation doesn't completely fill the given 472 * buffer in one read() call. 473 * 474 * @return A chunk of the desired size, or else a chunk as large as 475 * was available when end of stream was reached. Returns null if the 476 * given stream had no more data in it. 477 */ readChunk(InputStream in, final int chunkSize)478 private static ByteString readChunk(InputStream in, final int chunkSize) 479 throws IOException { 480 final byte[] buf = new byte[chunkSize]; 481 int bytesRead = 0; 482 while (bytesRead < chunkSize) { 483 final int count = in.read(buf, bytesRead, chunkSize - bytesRead); 484 if (count == -1) { 485 break; 486 } 487 bytesRead += count; 488 } 489 490 if (bytesRead == 0) { 491 return null; 492 } 493 494 // Always make a copy since InputStream could steal a reference to buf. 495 return ByteString.copyFrom(buf, 0, bytesRead); 496 } 497 498 // ================================================================= 499 // Multiple ByteStrings -> One ByteString 500 501 /** 502 * Concatenate the given {@code ByteString} to this one. Short concatenations, 503 * of total size smaller than {@link ByteString#CONCATENATE_BY_COPY_SIZE}, are 504 * produced by copying the underlying bytes (as per Rope.java, <a 505 * href="http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol25/issue12/spe986.pdf"> 506 * BAP95 </a>. In general, the concatenate involves no copying. 507 * 508 * @param other string to concatenate 509 * @return a new {@code ByteString} instance 510 */ concat(ByteString other)511 public final ByteString concat(ByteString other) { 512 if (Integer.MAX_VALUE - size() < other.size()) { 513 throw new IllegalArgumentException("ByteString would be too long: " + 514 size() + "+" + other.size()); 515 } 516 517 return RopeByteString.concatenate(this, other); 518 } 519 520 /** 521 * Concatenates all byte strings in the iterable and returns the result. 522 * This is designed to run in O(list size), not O(total bytes). 523 * 524 * <p>The returned {@code ByteString} is not necessarily a unique object. 525 * If the list is empty, the returned object is the singleton empty 526 * {@code ByteString}. If the list has only one element, that 527 * {@code ByteString} will be returned without copying. 528 * 529 * @param byteStrings strings to be concatenated 530 * @return new {@code ByteString} 531 */ copyFrom(Iterable<ByteString> byteStrings)532 public static ByteString copyFrom(Iterable<ByteString> byteStrings) { 533 // Determine the size; 534 final int size; 535 if (!(byteStrings instanceof Collection)) { 536 int tempSize = 0; 537 for (Iterator<ByteString> iter = byteStrings.iterator(); iter.hasNext(); 538 iter.next(), ++tempSize) { 539 } 540 size = tempSize; 541 } else { 542 size = ((Collection<ByteString>) byteStrings).size(); 543 } 544 545 if (size == 0) { 546 return EMPTY; 547 } 548 549 return balancedConcat(byteStrings.iterator(), size); 550 } 551 552 // Internal function used by copyFrom(Iterable<ByteString>). 553 // Create a balanced concatenation of the next "length" elements from the 554 // iterable. balancedConcat(Iterator<ByteString> iterator, int length)555 private static ByteString balancedConcat(Iterator<ByteString> iterator, int length) { 556 assert length >= 1; 557 ByteString result; 558 if (length == 1) { 559 result = iterator.next(); 560 } else { 561 int halfLength = length >>> 1; 562 ByteString left = balancedConcat(iterator, halfLength); 563 ByteString right = balancedConcat(iterator, length - halfLength); 564 result = left.concat(right); 565 } 566 return result; 567 } 568 569 // ================================================================= 570 // ByteString -> byte[] 571 572 /** 573 * Copies bytes into a buffer at the given offset. 574 * 575 * @param target buffer to copy into 576 * @param offset in the target buffer 577 * @throws IndexOutOfBoundsException if the offset is negative or too large 578 */ copyTo(byte[] target, int offset)579 public void copyTo(byte[] target, int offset) { 580 copyTo(target, 0, offset, size()); 581 } 582 583 /** 584 * Copies bytes into a buffer. 585 * 586 * @param target buffer to copy into 587 * @param sourceOffset offset within these bytes 588 * @param targetOffset offset within the target buffer 589 * @param numberToCopy number of bytes to copy 590 * @throws IndexOutOfBoundsException if an offset or size is negative or too 591 * large 592 */ copyTo(byte[] target, int sourceOffset, int targetOffset, int numberToCopy)593 public final void copyTo(byte[] target, int sourceOffset, int targetOffset, 594 int numberToCopy) { 595 checkRange(sourceOffset, sourceOffset + numberToCopy, size()); 596 checkRange(targetOffset, targetOffset + numberToCopy, target.length); 597 if (numberToCopy > 0) { 598 copyToInternal(target, sourceOffset, targetOffset, numberToCopy); 599 } 600 } 601 602 /** 603 * Internal (package private) implementation of 604 * {@link #copyTo(byte[],int,int,int)}. 605 * It assumes that all error checking has already been performed and that 606 * {@code numberToCopy > 0}. 607 */ copyToInternal(byte[] target, int sourceOffset, int targetOffset, int numberToCopy)608 protected abstract void copyToInternal(byte[] target, int sourceOffset, 609 int targetOffset, int numberToCopy); 610 611 /** 612 * Copies bytes into a ByteBuffer. 613 * 614 * @param target ByteBuffer to copy into. 615 * @throws java.nio.ReadOnlyBufferException if the {@code target} is read-only 616 * @throws java.nio.BufferOverflowException if the {@code target}'s 617 * remaining() space is not large enough to hold the data. 618 */ copyTo(ByteBuffer target)619 public abstract void copyTo(ByteBuffer target); 620 621 /** 622 * Copies bytes to a {@code byte[]}. 623 * 624 * @return copied bytes 625 */ toByteArray()626 public final byte[] toByteArray() { 627 final int size = size(); 628 if (size == 0) { 629 return Internal.EMPTY_BYTE_ARRAY; 630 } 631 byte[] result = new byte[size]; 632 copyToInternal(result, 0, 0, size); 633 return result; 634 } 635 636 /** 637 * Writes a copy of the contents of this byte string to the specified output stream argument. 638 * 639 * @param out the output stream to which to write the data. 640 * @throws IOException if an I/O error occurs. 641 */ writeTo(OutputStream out)642 public abstract void writeTo(OutputStream out) throws IOException; 643 644 /** 645 * Writes a specified part of this byte string to an output stream. 646 * 647 * @param out the output stream to which to write the data. 648 * @param sourceOffset offset within these bytes 649 * @param numberToWrite number of bytes to write 650 * @throws IOException if an I/O error occurs. 651 * @throws IndexOutOfBoundsException if an offset or size is negative or too large 652 */ writeTo(OutputStream out, int sourceOffset, int numberToWrite)653 final void writeTo(OutputStream out, int sourceOffset, int numberToWrite) 654 throws IOException { 655 checkRange(sourceOffset, sourceOffset + numberToWrite, size()); 656 if (numberToWrite > 0) { 657 writeToInternal(out, sourceOffset, numberToWrite); 658 } 659 } 660 661 /** 662 * Internal version of {@link #writeTo(OutputStream,int,int)} that assumes 663 * all error checking has already been done. 664 */ writeToInternal(OutputStream out, int sourceOffset, int numberToWrite)665 abstract void writeToInternal(OutputStream out, int sourceOffset, int numberToWrite) 666 throws IOException; 667 668 /** 669 * Writes this {@link ByteString} to the provided {@link ByteOutput}. Calling 670 * this method may result in multiple operations on the target {@link ByteOutput}. 671 * 672 * <p>This method may expose internal backing buffers of the {@link ByteString} to the {@link 673 * ByteOutput} in order to avoid additional copying overhead. It would be possible for a malicious 674 * {@link ByteOutput} to corrupt the {@link ByteString}. Use with caution! 675 * 676 * @param byteOutput the output target to receive the bytes 677 * @throws IOException if an I/O error occurs 678 * @see UnsafeByteOperations#unsafeWriteTo(ByteString, ByteOutput) 679 */ writeTo(ByteOutput byteOutput)680 abstract void writeTo(ByteOutput byteOutput) throws IOException; 681 682 /** 683 * Constructs a read-only {@code java.nio.ByteBuffer} whose content 684 * is equal to the contents of this byte string. 685 * The result uses the same backing array as the byte string, if possible. 686 * 687 * @return wrapped bytes 688 */ asReadOnlyByteBuffer()689 public abstract ByteBuffer asReadOnlyByteBuffer(); 690 691 /** 692 * Constructs a list of read-only {@code java.nio.ByteBuffer} objects 693 * such that the concatenation of their contents is equal to the contents 694 * of this byte string. The result uses the same backing arrays as the 695 * byte string. 696 * <p> 697 * By returning a list, implementations of this method may be able to avoid 698 * copying even when there are multiple backing arrays. 699 * 700 * @return a list of wrapped bytes 701 */ asReadOnlyByteBufferList()702 public abstract List<ByteBuffer> asReadOnlyByteBufferList(); 703 704 /** 705 * Constructs a new {@code String} by decoding the bytes using the 706 * specified charset. 707 * 708 * @param charsetName encode using this charset 709 * @return new string 710 * @throws UnsupportedEncodingException if charset isn't recognized 711 */ toString(String charsetName)712 public final String toString(String charsetName) 713 throws UnsupportedEncodingException { 714 try { 715 return toString(Charset.forName(charsetName)); 716 } catch (UnsupportedCharsetException e) { 717 UnsupportedEncodingException exception = new UnsupportedEncodingException(charsetName); 718 exception.initCause(e); 719 throw exception; 720 } 721 } 722 723 /** 724 * Constructs a new {@code String} by decoding the bytes using the 725 * specified charset. Returns the same empty String if empty. 726 * 727 * @param charset encode using this charset 728 * @return new string 729 */ toString(Charset charset)730 public final String toString(Charset charset) { 731 return size() == 0 ? "" : toStringInternal(charset); 732 } 733 734 /** 735 * Constructs a new {@code String} by decoding the bytes using the 736 * specified charset. 737 * 738 * @param charset encode using this charset 739 * @return new string 740 */ toStringInternal(Charset charset)741 protected abstract String toStringInternal(Charset charset); 742 743 // ================================================================= 744 // UTF-8 decoding 745 746 /** 747 * Constructs a new {@code String} by decoding the bytes as UTF-8. 748 * 749 * @return new string using UTF-8 encoding 750 */ toStringUtf8()751 public final String toStringUtf8() { 752 return toString(Internal.UTF_8); 753 } 754 755 /** 756 * Tells whether this {@code ByteString} represents a well-formed UTF-8 757 * byte sequence, such that the original bytes can be converted to a 758 * String object and then round tripped back to bytes without loss. 759 * 760 * <p>More precisely, returns {@code true} whenever: <pre> {@code 761 * Arrays.equals(byteString.toByteArray(), 762 * new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8")) 763 * }</pre> 764 * 765 * <p>This method returns {@code false} for "overlong" byte sequences, 766 * as well as for 3-byte sequences that would map to a surrogate 767 * character, in accordance with the restricted definition of UTF-8 768 * introduced in Unicode 3.1. Note that the UTF-8 decoder included in 769 * Oracle's JDK has been modified to also reject "overlong" byte 770 * sequences, but (as of 2011) still accepts 3-byte surrogate 771 * character byte sequences. 772 * 773 * <p>See the Unicode Standard,<br> 774 * Table 3-6. <em>UTF-8 Bit Distribution</em>,<br> 775 * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>. 776 * 777 * @return whether the bytes in this {@code ByteString} are a 778 * well-formed UTF-8 byte sequence 779 */ isValidUtf8()780 public abstract boolean isValidUtf8(); 781 782 /** 783 * Tells whether the given byte sequence is a well-formed, malformed, or 784 * incomplete UTF-8 byte sequence. This method accepts and returns a partial 785 * state result, allowing the bytes for a complete UTF-8 byte sequence to be 786 * composed from multiple {@code ByteString} segments. 787 * 788 * @param state either {@code 0} (if this is the initial decoding operation) 789 * or the value returned from a call to a partial decoding method for the 790 * previous bytes 791 * @param offset offset of the first byte to check 792 * @param length number of bytes to check 793 * 794 * @return {@code -1} if the partial byte sequence is definitely malformed, 795 * {@code 0} if it is well-formed (no additional input needed), or, if the 796 * byte sequence is "incomplete", i.e. apparently terminated in the middle of 797 * a character, an opaque integer "state" value containing enough information 798 * to decode the character when passed to a subsequent invocation of a 799 * partial decoding method. 800 */ partialIsValidUtf8(int state, int offset, int length)801 protected abstract int partialIsValidUtf8(int state, int offset, int length); 802 803 // ================================================================= 804 // equals() and hashCode() 805 806 @Override 807 public abstract boolean equals(Object o); 808 809 /** 810 * Base class for leaf {@link ByteString}s (i.e. non-ropes). 811 */ 812 abstract static class LeafByteString extends ByteString { 813 @Override getTreeDepth()814 protected final int getTreeDepth() { 815 return 0; 816 } 817 818 @Override isBalanced()819 protected final boolean isBalanced() { 820 return true; 821 } 822 823 /** 824 * Check equality of the substring of given length of this object starting at 825 * zero with another {@code ByteString} substring starting at offset. 826 * 827 * @param other what to compare a substring in 828 * @param offset offset into other 829 * @param length number of bytes to compare 830 * @return true for equality of substrings, else false. 831 */ equalsRange(ByteString other, int offset, int length)832 abstract boolean equalsRange(ByteString other, int offset, int length); 833 } 834 835 /** 836 * Compute the hashCode using the traditional algorithm from {@link 837 * ByteString}. 838 * 839 * @return hashCode value 840 */ 841 @Override hashCode()842 public final int hashCode() { 843 int h = hash; 844 845 if (h == 0) { 846 int size = size(); 847 h = partialHash(size, 0, size); 848 if (h == 0) { 849 h = 1; 850 } 851 hash = h; 852 } 853 return h; 854 } 855 856 // ================================================================= 857 // Input stream 858 859 /** 860 * Creates an {@code InputStream} which can be used to read the bytes. 861 * <p> 862 * The {@link InputStream} returned by this method is guaranteed to be 863 * completely non-blocking. The method {@link InputStream#available()} 864 * returns the number of bytes remaining in the stream. The methods 865 * {@link InputStream#read(byte[])}, {@link InputStream#read(byte[],int,int)} 866 * and {@link InputStream#skip(long)} will read/skip as many bytes as are 867 * available. The method {@link InputStream#markSupported()} returns 868 * {@code true}. 869 * <p> 870 * The methods in the returned {@link InputStream} might <b>not</b> be 871 * thread safe. 872 * 873 * @return an input stream that returns the bytes of this byte string. 874 */ newInput()875 public abstract InputStream newInput(); 876 877 /** 878 * Creates a {@link CodedInputStream} which can be used to read the bytes. 879 * Using this is often more efficient than creating a {@link CodedInputStream} 880 * that wraps the result of {@link #newInput()}. 881 * 882 * @return stream based on wrapped data 883 */ newCodedInput()884 public abstract CodedInputStream newCodedInput(); 885 886 // ================================================================= 887 // Output stream 888 889 /** 890 * Creates a new {@link Output} with the given initial capacity. Call {@link 891 * Output#toByteString()} to create the {@code ByteString} instance. 892 * <p> 893 * A {@link ByteString.Output} offers the same functionality as a 894 * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString} 895 * rather than a {@code byte} array. 896 * 897 * @param initialCapacity estimate of number of bytes to be written 898 * @return {@code OutputStream} for building a {@code ByteString} 899 */ newOutput(int initialCapacity)900 public static Output newOutput(int initialCapacity) { 901 return new Output(initialCapacity); 902 } 903 904 /** 905 * Creates a new {@link Output}. Call {@link Output#toByteString()} to create 906 * the {@code ByteString} instance. 907 * <p> 908 * A {@link ByteString.Output} offers the same functionality as a 909 * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString} 910 * rather than a {@code byte array}. 911 * 912 * @return {@code OutputStream} for building a {@code ByteString} 913 */ newOutput()914 public static Output newOutput() { 915 return new Output(CONCATENATE_BY_COPY_SIZE); 916 } 917 918 /** 919 * Outputs to a {@code ByteString} instance. Call {@link #toByteString()} to 920 * create the {@code ByteString} instance. 921 */ 922 public static final class Output extends OutputStream { 923 // Implementation note. 924 // The public methods of this class must be synchronized. ByteStrings 925 // are guaranteed to be immutable. Without some sort of locking, it could 926 // be possible for one thread to call toByteSring(), while another thread 927 // is still modifying the underlying byte array. 928 929 private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; 930 // argument passed by user, indicating initial capacity. 931 private final int initialCapacity; 932 // ByteStrings to be concatenated to create the result 933 private final ArrayList<ByteString> flushedBuffers; 934 // Total number of bytes in the ByteStrings of flushedBuffers 935 private int flushedBuffersTotalBytes; 936 // Current buffer to which we are writing 937 private byte[] buffer; 938 // Location in buffer[] to which we write the next byte. 939 private int bufferPos; 940 941 /** 942 * Creates a new ByteString output stream with the specified 943 * initial capacity. 944 * 945 * @param initialCapacity the initial capacity of the output stream. 946 */ Output(int initialCapacity)947 Output(int initialCapacity) { 948 if (initialCapacity < 0) { 949 throw new IllegalArgumentException("Buffer size < 0"); 950 } 951 this.initialCapacity = initialCapacity; 952 this.flushedBuffers = new ArrayList<ByteString>(); 953 this.buffer = new byte[initialCapacity]; 954 } 955 956 @Override write(int b)957 public synchronized void write(int b) { 958 if (bufferPos == buffer.length) { 959 flushFullBuffer(1); 960 } 961 buffer[bufferPos++] = (byte)b; 962 } 963 964 @Override write(byte[] b, int offset, int length)965 public synchronized void write(byte[] b, int offset, int length) { 966 if (length <= buffer.length - bufferPos) { 967 // The bytes can fit into the current buffer. 968 System.arraycopy(b, offset, buffer, bufferPos, length); 969 bufferPos += length; 970 } else { 971 // Use up the current buffer 972 int copySize = buffer.length - bufferPos; 973 System.arraycopy(b, offset, buffer, bufferPos, copySize); 974 offset += copySize; 975 length -= copySize; 976 // Flush the buffer, and get a new buffer at least big enough to cover 977 // what we still need to output 978 flushFullBuffer(length); 979 System.arraycopy(b, offset, buffer, 0 /* count */, length); 980 bufferPos = length; 981 } 982 } 983 984 /** 985 * Creates a byte string. Its size is the current size of this output 986 * stream and its output has been copied to it. 987 * 988 * @return the current contents of this output stream, as a byte string. 989 */ toByteString()990 public synchronized ByteString toByteString() { 991 flushLastBuffer(); 992 return ByteString.copyFrom(flushedBuffers); 993 } 994 995 /** 996 * Implement java.util.Arrays.copyOf() for jdk 1.5. 997 */ copyArray(byte[] buffer, int length)998 private byte[] copyArray(byte[] buffer, int length) { 999 byte[] result = new byte[length]; 1000 System.arraycopy(buffer, 0, result, 0, Math.min(buffer.length, length)); 1001 return result; 1002 } 1003 1004 /** 1005 * Writes the complete contents of this byte array output stream to 1006 * the specified output stream argument. 1007 * 1008 * @param out the output stream to which to write the data. 1009 * @throws IOException if an I/O error occurs. 1010 */ writeTo(OutputStream out)1011 public void writeTo(OutputStream out) throws IOException { 1012 ByteString[] cachedFlushBuffers; 1013 byte[] cachedBuffer; 1014 int cachedBufferPos; 1015 synchronized (this) { 1016 // Copy the information we need into local variables so as to hold 1017 // the lock for as short a time as possible. 1018 cachedFlushBuffers = 1019 flushedBuffers.toArray(new ByteString[flushedBuffers.size()]); 1020 cachedBuffer = buffer; 1021 cachedBufferPos = bufferPos; 1022 } 1023 for (ByteString byteString : cachedFlushBuffers) { 1024 byteString.writeTo(out); 1025 } 1026 1027 out.write(copyArray(cachedBuffer, cachedBufferPos)); 1028 } 1029 1030 /** 1031 * Returns the current size of the output stream. 1032 * 1033 * @return the current size of the output stream 1034 */ size()1035 public synchronized int size() { 1036 return flushedBuffersTotalBytes + bufferPos; 1037 } 1038 1039 /** 1040 * Resets this stream, so that all currently accumulated output in the 1041 * output stream is discarded. The output stream can be used again, 1042 * reusing the already allocated buffer space. 1043 */ reset()1044 public synchronized void reset() { 1045 flushedBuffers.clear(); 1046 flushedBuffersTotalBytes = 0; 1047 bufferPos = 0; 1048 } 1049 1050 @Override toString()1051 public String toString() { 1052 return String.format("<ByteString.Output@%s size=%d>", 1053 Integer.toHexString(System.identityHashCode(this)), size()); 1054 } 1055 1056 /** 1057 * Internal function used by writers. The current buffer is full, and the 1058 * writer needs a new buffer whose size is at least the specified minimum 1059 * size. 1060 */ flushFullBuffer(int minSize)1061 private void flushFullBuffer(int minSize) { 1062 flushedBuffers.add(new LiteralByteString(buffer)); 1063 flushedBuffersTotalBytes += buffer.length; 1064 // We want to increase our total capacity by 50%, but as a minimum, 1065 // the new buffer should also at least be >= minSize and 1066 // >= initial Capacity. 1067 int newSize = Math.max(initialCapacity, 1068 Math.max(minSize, flushedBuffersTotalBytes >>> 1)); 1069 buffer = new byte[newSize]; 1070 bufferPos = 0; 1071 } 1072 1073 /** 1074 * Internal function used by {@link #toByteString()}. The current buffer may 1075 * or may not be full, but it needs to be flushed. 1076 */ flushLastBuffer()1077 private void flushLastBuffer() { 1078 if (bufferPos < buffer.length) { 1079 if (bufferPos > 0) { 1080 byte[] bufferCopy = copyArray(buffer, bufferPos); 1081 flushedBuffers.add(new LiteralByteString(bufferCopy)); 1082 } 1083 // We reuse this buffer for further writes. 1084 } else { 1085 // Buffer is completely full. Huzzah. 1086 flushedBuffers.add(new LiteralByteString(buffer)); 1087 // 99% of the time, we're not going to use this OutputStream again. 1088 // We set buffer to an empty byte stream so that we're handling this 1089 // case without wasting space. In the rare case that more writes 1090 // *do* occur, this empty buffer will be flushed and an appropriately 1091 // sized new buffer will be created. 1092 buffer = EMPTY_BYTE_ARRAY; 1093 } 1094 flushedBuffersTotalBytes += bufferPos; 1095 bufferPos = 0; 1096 } 1097 } 1098 1099 /** 1100 * Constructs a new {@code ByteString} builder, which allows you to 1101 * efficiently construct a {@code ByteString} by writing to a {@link 1102 * CodedOutputStream}. Using this is much more efficient than calling {@code 1103 * newOutput()} and wrapping that in a {@code CodedOutputStream}. 1104 * 1105 * <p>This is package-private because it's a somewhat confusing interface. 1106 * Users can call {@link Message#toByteString()} instead of calling this 1107 * directly. 1108 * 1109 * @param size The target byte size of the {@code ByteString}. You must write 1110 * exactly this many bytes before building the result. 1111 * @return the builder 1112 */ newCodedBuilder(int size)1113 static CodedBuilder newCodedBuilder(int size) { 1114 return new CodedBuilder(size); 1115 } 1116 1117 /** See {@link ByteString#newCodedBuilder(int)}. */ 1118 static final class CodedBuilder { 1119 private final CodedOutputStream output; 1120 private final byte[] buffer; 1121 CodedBuilder(int size)1122 private CodedBuilder(int size) { 1123 buffer = new byte[size]; 1124 output = CodedOutputStream.newInstance(buffer); 1125 } 1126 build()1127 public ByteString build() { 1128 output.checkNoSpaceLeft(); 1129 1130 // We can be confident that the CodedOutputStream will not modify the 1131 // underlying bytes anymore because it already wrote all of them. So, 1132 // no need to make a copy. 1133 return new LiteralByteString(buffer); 1134 } 1135 getCodedOutput()1136 public CodedOutputStream getCodedOutput() { 1137 return output; 1138 } 1139 } 1140 1141 // ================================================================= 1142 // Methods {@link RopeByteString} needs on instances, which aren't part of the 1143 // public API. 1144 1145 /** 1146 * Return the depth of the tree representing this {@code ByteString}, if any, 1147 * whose root is this node. If this is a leaf node, return 0. 1148 * 1149 * @return tree depth or zero 1150 */ getTreeDepth()1151 protected abstract int getTreeDepth(); 1152 1153 /** 1154 * Return {@code true} if this ByteString is literal (a leaf node) or a 1155 * flat-enough tree in the sense of {@link RopeByteString}. 1156 * 1157 * @return true if the tree is flat enough 1158 */ isBalanced()1159 protected abstract boolean isBalanced(); 1160 1161 /** 1162 * Return the cached hash code if available. 1163 * 1164 * @return value of cached hash code or 0 if not computed yet 1165 */ peekCachedHashCode()1166 protected final int peekCachedHashCode() { 1167 return hash; 1168 } 1169 1170 /** 1171 * Compute the hash across the value bytes starting with the given hash, and 1172 * return the result. This is used to compute the hash across strings 1173 * represented as a set of pieces by allowing the hash computation to be 1174 * continued from piece to piece. 1175 * 1176 * @param h starting hash value 1177 * @param offset offset into this value to start looking at data values 1178 * @param length number of data values to include in the hash computation 1179 * @return ending hash value 1180 */ partialHash(int h, int offset, int length)1181 protected abstract int partialHash(int h, int offset, int length); 1182 1183 /** 1184 * Checks that the given index falls within the specified array size. 1185 * 1186 * @param index the index position to be tested 1187 * @param size the length of the array 1188 * @throws IndexOutOfBoundsException if the index does not fall within the array. 1189 */ checkIndex(int index, int size)1190 static void checkIndex(int index, int size) { 1191 if ((index | (size - (index + 1))) < 0) { 1192 if (index < 0) { 1193 throw new ArrayIndexOutOfBoundsException("Index < 0: " + index); 1194 } 1195 throw new ArrayIndexOutOfBoundsException("Index > length: " + index + ", " + size); 1196 } 1197 } 1198 1199 /** 1200 * Checks that the given range falls within the bounds of an array 1201 * 1202 * @param startIndex the start index of the range (inclusive) 1203 * @param endIndex the end index of the range (exclusive) 1204 * @param size the size of the array. 1205 * @return the length of the range. 1206 * @throws IndexOutOfBoundsException some or all of the range falls outside of the array. 1207 */ checkRange(int startIndex, int endIndex, int size)1208 static int checkRange(int startIndex, int endIndex, int size) { 1209 final int length = endIndex - startIndex; 1210 if ((startIndex | endIndex | length | (size - endIndex)) < 0) { 1211 if (startIndex < 0) { 1212 throw new IndexOutOfBoundsException("Beginning index: " + startIndex + " < 0"); 1213 } 1214 if (endIndex < startIndex) { 1215 throw new IndexOutOfBoundsException( 1216 "Beginning index larger than ending index: " + startIndex + ", " + endIndex); 1217 } 1218 // endIndex >= size 1219 throw new IndexOutOfBoundsException("End index: " + endIndex + " >= " + size); 1220 } 1221 return length; 1222 } 1223 1224 @Override toString()1225 public final String toString() { 1226 return String.format("<ByteString@%s size=%d>", 1227 Integer.toHexString(System.identityHashCode(this)), size()); 1228 } 1229 1230 /** 1231 * This class implements a {@link com.google.protobuf.ByteString} backed by a 1232 * single array of bytes, contiguous in memory. It supports substring by 1233 * pointing to only a sub-range of the underlying byte array, meaning that a 1234 * substring will reference the full byte-array of the string it's made from, 1235 * exactly as with {@link String}. 1236 * 1237 * @author carlanton@google.com (Carl Haverl) 1238 */ 1239 // Keep this class private to avoid deadlocks in classloading across threads as ByteString's 1240 // static initializer loads LiteralByteString and another thread loads LiteralByteString. 1241 private static class LiteralByteString extends ByteString.LeafByteString { 1242 private static final long serialVersionUID = 1L; 1243 1244 protected final byte[] bytes; 1245 1246 /** 1247 * Creates a {@code LiteralByteString} backed by the given array, without 1248 * copying. 1249 * 1250 * @param bytes array to wrap 1251 */ LiteralByteString(byte[] bytes)1252 LiteralByteString(byte[] bytes) { 1253 this.bytes = bytes; 1254 } 1255 1256 @Override byteAt(int index)1257 public byte byteAt(int index) { 1258 // Unlike most methods in this class, this one is a direct implementation 1259 // ignoring the potential offset because we need to do range-checking in the 1260 // substring case anyway. 1261 return bytes[index]; 1262 } 1263 1264 @Override size()1265 public int size() { 1266 return bytes.length; 1267 } 1268 1269 // ================================================================= 1270 // ByteString -> substring 1271 1272 @Override substring(int beginIndex, int endIndex)1273 public final ByteString substring(int beginIndex, int endIndex) { 1274 final int length = checkRange(beginIndex, endIndex, size()); 1275 1276 if (length == 0) { 1277 return ByteString.EMPTY; 1278 } 1279 1280 return new BoundedByteString(bytes, getOffsetIntoBytes() + beginIndex, length); 1281 } 1282 1283 // ================================================================= 1284 // ByteString -> byte[] 1285 1286 @Override copyToInternal( byte[] target, int sourceOffset, int targetOffset, int numberToCopy)1287 protected void copyToInternal( 1288 byte[] target, int sourceOffset, int targetOffset, int numberToCopy) { 1289 // Optimized form, not for subclasses, since we don't call 1290 // getOffsetIntoBytes() or check the 'numberToCopy' parameter. 1291 // TODO(nathanmittler): Is not calling getOffsetIntoBytes really saving that much? 1292 System.arraycopy(bytes, sourceOffset, target, targetOffset, numberToCopy); 1293 } 1294 1295 @Override copyTo(ByteBuffer target)1296 public final void copyTo(ByteBuffer target) { 1297 target.put(bytes, getOffsetIntoBytes(), size()); // Copies bytes 1298 } 1299 1300 @Override asReadOnlyByteBuffer()1301 public final ByteBuffer asReadOnlyByteBuffer() { 1302 return ByteBuffer.wrap(bytes, getOffsetIntoBytes(), size()).asReadOnlyBuffer(); 1303 } 1304 1305 @Override asReadOnlyByteBufferList()1306 public final List<ByteBuffer> asReadOnlyByteBufferList() { 1307 return Collections.singletonList(asReadOnlyByteBuffer()); 1308 } 1309 1310 @Override writeTo(OutputStream outputStream)1311 public final void writeTo(OutputStream outputStream) throws IOException { 1312 outputStream.write(toByteArray()); 1313 } 1314 1315 @Override writeToInternal(OutputStream outputStream, int sourceOffset, int numberToWrite)1316 final void writeToInternal(OutputStream outputStream, int sourceOffset, int numberToWrite) 1317 throws IOException { 1318 outputStream.write(bytes, getOffsetIntoBytes() + sourceOffset, numberToWrite); 1319 } 1320 1321 @Override writeTo(ByteOutput output)1322 final void writeTo(ByteOutput output) throws IOException { 1323 output.writeLazy(bytes, getOffsetIntoBytes(), size()); 1324 } 1325 1326 @Override toStringInternal(Charset charset)1327 protected final String toStringInternal(Charset charset) { 1328 return new String(bytes, getOffsetIntoBytes(), size(), charset); 1329 } 1330 1331 // ================================================================= 1332 // UTF-8 decoding 1333 1334 @Override isValidUtf8()1335 public final boolean isValidUtf8() { 1336 int offset = getOffsetIntoBytes(); 1337 return Utf8.isValidUtf8(bytes, offset, offset + size()); 1338 } 1339 1340 @Override partialIsValidUtf8(int state, int offset, int length)1341 protected final int partialIsValidUtf8(int state, int offset, int length) { 1342 int index = getOffsetIntoBytes() + offset; 1343 return Utf8.partialIsValidUtf8(state, bytes, index, index + length); 1344 } 1345 1346 // ================================================================= 1347 // equals() and hashCode() 1348 1349 @Override equals(Object other)1350 public final boolean equals(Object other) { 1351 if (other == this) { 1352 return true; 1353 } 1354 if (!(other instanceof ByteString)) { 1355 return false; 1356 } 1357 1358 if (size() != ((ByteString) other).size()) { 1359 return false; 1360 } 1361 if (size() == 0) { 1362 return true; 1363 } 1364 1365 if (other instanceof LiteralByteString) { 1366 LiteralByteString otherAsLiteral = (LiteralByteString) other; 1367 // If we know the hash codes and they are not equal, we know the byte 1368 // strings are not equal. 1369 int thisHash = peekCachedHashCode(); 1370 int thatHash = otherAsLiteral.peekCachedHashCode(); 1371 if (thisHash != 0 && thatHash != 0 && thisHash != thatHash) { 1372 return false; 1373 } 1374 1375 return equalsRange((LiteralByteString) other, 0, size()); 1376 } else { 1377 // RopeByteString and NioByteString. 1378 return other.equals(this); 1379 } 1380 } 1381 1382 /** 1383 * Check equality of the substring of given length of this object starting at 1384 * zero with another {@code LiteralByteString} substring starting at offset. 1385 * 1386 * @param other what to compare a substring in 1387 * @param offset offset into other 1388 * @param length number of bytes to compare 1389 * @return true for equality of substrings, else false. 1390 */ 1391 @Override equalsRange(ByteString other, int offset, int length)1392 final boolean equalsRange(ByteString other, int offset, int length) { 1393 if (length > other.size()) { 1394 throw new IllegalArgumentException("Length too large: " + length + size()); 1395 } 1396 if (offset + length > other.size()) { 1397 throw new IllegalArgumentException( 1398 "Ran off end of other: " + offset + ", " + length + ", " + other.size()); 1399 } 1400 1401 if (other instanceof LiteralByteString) { 1402 LiteralByteString lbsOther = (LiteralByteString) other; 1403 byte[] thisBytes = bytes; 1404 byte[] otherBytes = lbsOther.bytes; 1405 int thisLimit = getOffsetIntoBytes() + length; 1406 for ( 1407 int thisIndex = getOffsetIntoBytes(), 1408 otherIndex = lbsOther.getOffsetIntoBytes() + offset; 1409 (thisIndex < thisLimit); ++thisIndex, ++otherIndex) { 1410 if (thisBytes[thisIndex] != otherBytes[otherIndex]) { 1411 return false; 1412 } 1413 } 1414 return true; 1415 } 1416 1417 return other.substring(offset, offset + length).equals(substring(0, length)); 1418 } 1419 1420 @Override partialHash(int h, int offset, int length)1421 protected final int partialHash(int h, int offset, int length) { 1422 return Internal.partialHash(h, bytes, getOffsetIntoBytes() + offset, length); 1423 } 1424 1425 // ================================================================= 1426 // Input stream 1427 1428 @Override newInput()1429 public final InputStream newInput() { 1430 return new ByteArrayInputStream(bytes, getOffsetIntoBytes(), size()); // No copy 1431 } 1432 1433 @Override newCodedInput()1434 public final CodedInputStream newCodedInput() { 1435 // We trust CodedInputStream not to modify the bytes, or to give anyone 1436 // else access to them. 1437 return CodedInputStream.newInstance( 1438 bytes, getOffsetIntoBytes(), size(), true /* bufferIsImmutable */); 1439 } 1440 1441 // ================================================================= 1442 // Internal methods 1443 1444 /** 1445 * Offset into {@code bytes[]} to use, non-zero for substrings. 1446 * 1447 * @return always 0 for this class 1448 */ getOffsetIntoBytes()1449 protected int getOffsetIntoBytes() { 1450 return 0; 1451 } 1452 } 1453 1454 /** 1455 * This class is used to represent the substring of a {@link ByteString} over a 1456 * single byte array. In terms of the public API of {@link ByteString}, you end 1457 * up here by calling {@link ByteString#copyFrom(byte[])} followed by {@link 1458 * ByteString#substring(int, int)}. 1459 * 1460 * <p>This class contains most of the overhead involved in creating a substring 1461 * from a {@link LiteralByteString}. The overhead involves some range-checking 1462 * and two extra fields. 1463 * 1464 * @author carlanton@google.com (Carl Haverl) 1465 */ 1466 // Keep this class private to avoid deadlocks in classloading across threads as ByteString's 1467 // static initializer loads LiteralByteString and another thread loads BoundedByteString. 1468 private static final class BoundedByteString extends LiteralByteString { 1469 1470 private final int bytesOffset; 1471 private final int bytesLength; 1472 1473 /** 1474 * Creates a {@code BoundedByteString} backed by the sub-range of given array, 1475 * without copying. 1476 * 1477 * @param bytes array to wrap 1478 * @param offset index to first byte to use in bytes 1479 * @param length number of bytes to use from bytes 1480 * @throws IllegalArgumentException if {@code offset < 0}, {@code length < 0}, 1481 * or if {@code offset + length > 1482 * bytes.length}. 1483 */ BoundedByteString(byte[] bytes, int offset, int length)1484 BoundedByteString(byte[] bytes, int offset, int length) { 1485 super(bytes); 1486 checkRange(offset, offset + length, bytes.length); 1487 1488 this.bytesOffset = offset; 1489 this.bytesLength = length; 1490 } 1491 1492 /** 1493 * Gets the byte at the given index. 1494 * Throws {@link ArrayIndexOutOfBoundsException} 1495 * for backwards-compatibility reasons although it would more properly be 1496 * {@link IndexOutOfBoundsException}. 1497 * 1498 * @param index index of byte 1499 * @return the value 1500 * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size 1501 */ 1502 @Override byteAt(int index)1503 public byte byteAt(int index) { 1504 // We must check the index ourselves as we cannot rely on Java array index 1505 // checking for substrings. 1506 checkIndex(index, size()); 1507 return bytes[bytesOffset + index]; 1508 } 1509 1510 @Override size()1511 public int size() { 1512 return bytesLength; 1513 } 1514 1515 @Override getOffsetIntoBytes()1516 protected int getOffsetIntoBytes() { 1517 return bytesOffset; 1518 } 1519 1520 // ================================================================= 1521 // ByteString -> byte[] 1522 1523 @Override copyToInternal(byte[] target, int sourceOffset, int targetOffset, int numberToCopy)1524 protected void copyToInternal(byte[] target, int sourceOffset, int targetOffset, 1525 int numberToCopy) { 1526 System.arraycopy(bytes, getOffsetIntoBytes() + sourceOffset, target, 1527 targetOffset, numberToCopy); 1528 } 1529 1530 // ================================================================= 1531 // Serializable 1532 1533 private static final long serialVersionUID = 1L; 1534 writeReplace()1535 Object writeReplace() { 1536 return ByteString.wrap(toByteArray()); 1537 } 1538 readObject(@uppressWarnings"unused") ObjectInputStream in)1539 private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws IOException { 1540 throw new InvalidObjectException( 1541 "BoundedByteStream instances are not to be serialized directly"); 1542 } 1543 } 1544 } 1545