| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 import java.nio.charset.UnsupportedCharsetException; | 44 import java.nio.charset.UnsupportedCharsetException; |
| 45 import java.util.ArrayList; | 45 import java.util.ArrayList; |
| 46 import java.util.Arrays; | 46 import java.util.Arrays; |
| 47 import java.util.Collection; | 47 import java.util.Collection; |
| 48 import java.util.Collections; | 48 import java.util.Collections; |
| 49 import java.util.Iterator; | 49 import java.util.Iterator; |
| 50 import java.util.List; | 50 import java.util.List; |
| 51 import java.util.NoSuchElementException; | 51 import java.util.NoSuchElementException; |
| 52 | 52 |
| 53 /** | 53 /** |
| 54 * Immutable sequence of bytes. Substring is supported by sharing the reference
to the immutable | 54 * Immutable sequence of bytes. Substring is supported by sharing the reference |
| 55 * underlying bytes. Concatenation is likewise supported without copying (long s
trings) by building | 55 * to the immutable underlying bytes, as with {@link String}. Concatenation is |
| 56 * a tree of pieces in {@link RopeByteString}. | 56 * likewise supported without copying (long strings) by building a tree of |
| 57 * | 57 * pieces in {@link RopeByteString}. |
| 58 * <p>Like {@link String}, the contents of a {@link ByteString} can never be obs
erved to change, not | 58 * <p> |
| 59 * even in the presence of a data race or incorrect API usage in the client code
. | 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. |
| 60 * | 62 * |
| 61 * @author crazybob@google.com Bob Lee | 63 * @author crazybob@google.com Bob Lee |
| 62 * @author kenton@google.com Kenton Varda | 64 * @author kenton@google.com Kenton Varda |
| 63 * @author carlanton@google.com Carl Haverl | 65 * @author carlanton@google.com Carl Haverl |
| 64 * @author martinrb@google.com Martin Buchholz | 66 * @author martinrb@google.com Martin Buchholz |
| 65 */ | 67 */ |
| 66 public abstract class ByteString implements Iterable<Byte>, Serializable { | 68 public abstract class ByteString implements Iterable<Byte>, Serializable { |
| 67 | 69 |
| 68 /** | 70 /** |
| 69 * When two strings to be concatenated have a combined length shorter than | 71 * When two strings to be concatenated have a combined length shorter than |
| 70 * this, we just copy their bytes on {@link #concat(ByteString)}. | 72 * this, we just copy their bytes on {@link #concat(ByteString)}. |
| 71 * The trade-off is copy size versus the overhead of creating tree nodes | 73 * The trade-off is copy size versus the overhead of creating tree nodes |
| 72 * in {@link RopeByteString}. | 74 * in {@link RopeByteString}. |
| 73 */ | 75 */ |
| 74 static final int CONCATENATE_BY_COPY_SIZE = 128; | 76 static final int CONCATENATE_BY_COPY_SIZE = 128; |
| 75 | 77 |
| 76 /** | 78 /** |
| 77 * When copying an InputStream into a ByteString with .readFrom(), | 79 * When copying an InputStream into a ByteString with .readFrom(), |
| 78 * the chunks in the underlying rope start at 256 bytes, but double | 80 * the chunks in the underlying rope start at 256 bytes, but double |
| 79 * each iteration up to 8192 bytes. | 81 * each iteration up to 8192 bytes. |
| 80 */ | 82 */ |
| 81 static final int MIN_READ_FROM_CHUNK_SIZE = 0x100; // 256b | 83 static final int MIN_READ_FROM_CHUNK_SIZE = 0x100; // 256b |
| 82 static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000; // 8k | 84 static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000; // 8k |
| 83 | 85 |
| 84 /** | 86 /** |
| 85 * Empty {@code ByteString}. | 87 * Empty {@code ByteString}. |
| 86 */ | 88 */ |
| 87 public static final ByteString EMPTY = new LiteralByteString(Internal.EMPTY_BY
TE_ARRAY); | 89 public static final ByteString EMPTY = new LiteralByteString(Internal.EMPTY_BY
TE_ARRAY); |
| 88 | 90 |
| 89 /** | 91 /** |
| 90 * An interface to efficiently copy {@code byte[]}. | 92 * An interface to efficiently copy {@code byte[]}. |
| 91 * | 93 * |
| 92 * <p>One of the noticeable costs of copying a byte[] into a new array using | 94 * <p>One of the noticable costs of copying a byte[] into a new array using |
| 93 * {@code System.arraycopy} is nullification of a new buffer before the copy.
It has been shown | 95 * {@code System.arraycopy} is nullification of a new buffer before the copy.
It has been shown |
| 94 * the Hotspot VM is capable to intrisicfy {@code Arrays.copyOfRange} operatio
n to avoid this | 96 * the Hotspot VM is capable to intrisicfy {@code Arrays.copyOfRange} operatio
n to avoid this |
| 95 * expensive nullification and provide substantial performance gain. Unfortuna
tely this does not | 97 * expensive nullification and provide substantial performance gain. Unfortuna
tely this does not |
| 96 * hold on Android runtimes and could make the copy slightly slower due to add
itional code in | 98 * hold on Android runtimes and could make the copy slightly slower due to add
itional code in |
| 97 * the {@code Arrays.copyOfRange}. Thus we provide two different implementatio
n for array copier | 99 * the {@code Arrays.copyOfRange}. Thus we provide two different implementatio
n for array copier |
| 98 * for Hotspot and Android runtimes. | 100 * for Hotspot and Android runtimes. |
| 99 */ | 101 */ |
| 100 private interface ByteArrayCopier { | 102 private interface ByteArrayCopier { |
| 101 /** | 103 /** |
| 102 * Copies the specified range of the specified array into a new array | 104 * Copies the specified range of the specified array into a new array |
| 103 */ | 105 */ |
| 104 byte[] copyFrom(byte[] bytes, int offset, int size); | 106 byte[] copyFrom(byte[] bytes, int offset, int size); |
| 105 } | 107 } |
| 106 | 108 |
| 107 /** Implementation of {@code ByteArrayCopier} which uses {@link System#arrayco
py}. */ | 109 /** Implementation of {@code ByteArrayCopier} which uses {@link System#arrayco
py}. */ |
| 108 private static final class SystemByteArrayCopier implements ByteArrayCopier { | 110 private static final class SystemByteArrayCopier implements ByteArrayCopier { |
| 109 @Override | 111 @Override |
| 110 public byte[] copyFrom(byte[] bytes, int offset, int size) { | 112 public byte[] copyFrom(byte[] bytes, int offset, int size) { |
| 111 byte[] copy = new byte[size]; | 113 byte[] copy = new byte[size]; |
| 112 System.arraycopy(bytes, offset, copy, 0, size); | 114 System.arraycopy(bytes, offset, copy, 0, size); |
| 113 return copy; | 115 return copy; |
| 114 } | 116 } |
| 115 } | 117 } |
| 116 | 118 |
| 117 /** Implementation of {@code ByteArrayCopier} which uses {@link Arrays#copyOfR
ange}. */ | 119 /** Implementation of {@code ByteArrayCopier} which uses {@link Arrays#copyOfR
ange}. */ |
| 118 private static final class ArraysByteArrayCopier implements ByteArrayCopier { | 120 private static final class ArraysByteArrayCopier implements ByteArrayCopier { |
| 119 @Override | 121 @Override |
| 120 public byte[] copyFrom(byte[] bytes, int offset, int size) { | 122 public byte[] copyFrom(byte[] bytes, int offset, int size) { |
| 121 return Arrays.copyOfRange(bytes, offset, offset + size); | 123 return Arrays.copyOfRange(bytes, offset, offset + size); |
| 122 } | 124 } |
| 123 } | 125 } |
| 124 | 126 |
| 125 private static final ByteArrayCopier byteArrayCopier; | 127 private static final ByteArrayCopier byteArrayCopier; |
| 126 static { | 128 static { |
| 127 boolean isAndroid = true; | 129 boolean isAndroid = true; |
| 128 try { | 130 try { |
| 129 Class.forName("android.content.Context"); | 131 Class.forName("android.content.Context"); |
| 130 } catch (ClassNotFoundException e) { | 132 } catch (ClassNotFoundException e) { |
| 131 isAndroid = false; | 133 isAndroid = false; |
| 132 } | 134 } |
| 133 | 135 |
| 134 byteArrayCopier = isAndroid ? new SystemByteArrayCopier() : new ArraysByteAr
rayCopier(); | 136 byteArrayCopier = isAndroid ? new SystemByteArrayCopier() : new ArraysByteAr
rayCopier(); |
| 135 } | 137 } |
| 136 | 138 |
| 137 /** | 139 /** |
| 138 * Cached hash value. Intentionally accessed via a data race, which | 140 * Cached hash value. Intentionally accessed via a data race, which |
| 139 * is safe because of the Java Memory Model's "no out-of-thin-air values" | 141 * is safe because of the Java Memory Model's "no out-of-thin-air values" |
| 140 * guarantees for ints. A value of 0 implies that the hash has not been set. | 142 * guarantees for ints. A value of 0 implies that the hash has not been set. |
| 141 */ | 143 */ |
| 142 private int hash = 0; | 144 private int hash = 0; |
| 143 | 145 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 | 302 |
| 301 /** | 303 /** |
| 302 * Copies the given bytes into a {@code ByteString}. | 304 * Copies the given bytes into a {@code ByteString}. |
| 303 * | 305 * |
| 304 * @param bytes to copy | 306 * @param bytes to copy |
| 305 * @return new {@code ByteString} | 307 * @return new {@code ByteString} |
| 306 */ | 308 */ |
| 307 public static ByteString copyFrom(byte[] bytes) { | 309 public static ByteString copyFrom(byte[] bytes) { |
| 308 return copyFrom(bytes, 0, bytes.length); | 310 return copyFrom(bytes, 0, bytes.length); |
| 309 } | 311 } |
| 310 | 312 |
| 311 /** | |
| 312 * Wraps the given bytes into a {@code ByteString}. Intended for internal only
usage. | |
| 313 */ | |
| 314 static ByteString wrap(ByteBuffer buffer) { | |
| 315 if (buffer.hasArray()) { | |
| 316 final int offset = buffer.arrayOffset(); | |
| 317 return ByteString.wrap(buffer.array(), offset + buffer.position(), buffer.
remaining()); | |
| 318 } else { | |
| 319 return new NioByteString(buffer); | |
| 320 } | |
| 321 } | |
| 322 | |
| 323 /** | 313 /** |
| 324 * Wraps the given bytes into a {@code ByteString}. Intended for internal only | 314 * Wraps the given bytes into a {@code ByteString}. Intended for internal only |
| 325 * usage to force a classload of ByteString before LiteralByteString. | 315 * usage to force a classload of ByteString before LiteralByteString. |
| 326 */ | 316 */ |
| 327 static ByteString wrap(byte[] bytes) { | 317 static ByteString wrap(byte[] bytes) { |
| 328 // TODO(dweis): Return EMPTY when bytes are empty to reduce allocations? | 318 // TODO(dweis): Return EMPTY when bytes are empty to reduce allocations? |
| 329 return new LiteralByteString(bytes); | 319 return new LiteralByteString(bytes); |
| 330 } | 320 } |
| 331 | 321 |
| 332 /** | 322 /** |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 | 395 |
| 406 /** | 396 /** |
| 407 * Completely reads the given stream's bytes into a | 397 * Completely reads the given stream's bytes into a |
| 408 * {@code ByteString}, blocking if necessary until all bytes are | 398 * {@code ByteString}, blocking if necessary until all bytes are |
| 409 * read through to the end of the stream. | 399 * read through to the end of the stream. |
| 410 * | 400 * |
| 411 * <b>Performance notes:</b> The returned {@code ByteString} is an | 401 * <b>Performance notes:</b> The returned {@code ByteString} is an |
| 412 * immutable tree of byte arrays ("chunks") of the stream data. The | 402 * immutable tree of byte arrays ("chunks") of the stream data. The |
| 413 * first chunk is small, with subsequent chunks each being double | 403 * first chunk is small, with subsequent chunks each being double |
| 414 * the size, up to 8K. | 404 * the size, up to 8K. |
| 415 * | 405 * |
| 416 * <p>Each byte read from the input stream will be copied twice to ensure | 406 * <p>Each byte read from the input stream will be copied twice to ensure |
| 417 * that the resulting ByteString is truly immutable. | 407 * that the resulting ByteString is truly immutable. |
| 418 * | 408 * |
| 419 * @param streamToDrain The source stream, which is read completely | 409 * @param streamToDrain The source stream, which is read completely |
| 420 * but not closed. | 410 * but not closed. |
| 421 * @return A new {@code ByteString} which is made up of chunks of | 411 * @return A new {@code ByteString} which is made up of chunks of |
| 422 * various sizes, depending on the behavior of the underlying | 412 * various sizes, depending on the behavior of the underlying |
| 423 * stream. | 413 * stream. |
| 424 * @throws IOException IOException is thrown if there is a problem | 414 * @throws IOException IOException is thrown if there is a problem |
| 425 * reading the underlying stream. | 415 * reading the underlying stream. |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 return EMPTY; | 546 return EMPTY; |
| 557 } | 547 } |
| 558 | 548 |
| 559 return balancedConcat(byteStrings.iterator(), size); | 549 return balancedConcat(byteStrings.iterator(), size); |
| 560 } | 550 } |
| 561 | 551 |
| 562 // Internal function used by copyFrom(Iterable<ByteString>). | 552 // Internal function used by copyFrom(Iterable<ByteString>). |
| 563 // Create a balanced concatenation of the next "length" elements from the | 553 // Create a balanced concatenation of the next "length" elements from the |
| 564 // iterable. | 554 // iterable. |
| 565 private static ByteString balancedConcat(Iterator<ByteString> iterator, int le
ngth) { | 555 private static ByteString balancedConcat(Iterator<ByteString> iterator, int le
ngth) { |
| 566 if (length < 1) { | 556 assert length >= 1; |
| 567 throw new IllegalArgumentException(String.format("length (%s) must be >= 1
", length)); | |
| 568 } | |
| 569 ByteString result; | 557 ByteString result; |
| 570 if (length == 1) { | 558 if (length == 1) { |
| 571 result = iterator.next(); | 559 result = iterator.next(); |
| 572 } else { | 560 } else { |
| 573 int halfLength = length >>> 1; | 561 int halfLength = length >>> 1; |
| 574 ByteString left = balancedConcat(iterator, halfLength); | 562 ByteString left = balancedConcat(iterator, halfLength); |
| 575 ByteString right = balancedConcat(iterator, length - halfLength); | 563 ByteString right = balancedConcat(iterator, length - halfLength); |
| 576 result = left.concat(right); | 564 result = left.concat(right); |
| 577 } | 565 } |
| 578 return result; | 566 return result; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 * <p>This method may expose internal backing buffers of the {@link ByteString
} to the {@link | 672 * <p>This method may expose internal backing buffers of the {@link ByteString
} to the {@link |
| 685 * ByteOutput} in order to avoid additional copying overhead. It would be poss
ible for a malicious | 673 * ByteOutput} in order to avoid additional copying overhead. It would be poss
ible for a malicious |
| 686 * {@link ByteOutput} to corrupt the {@link ByteString}. Use with caution! | 674 * {@link ByteOutput} to corrupt the {@link ByteString}. Use with caution! |
| 687 * | 675 * |
| 688 * @param byteOutput the output target to receive the bytes | 676 * @param byteOutput the output target to receive the bytes |
| 689 * @throws IOException if an I/O error occurs | 677 * @throws IOException if an I/O error occurs |
| 690 * @see UnsafeByteOperations#unsafeWriteTo(ByteString, ByteOutput) | 678 * @see UnsafeByteOperations#unsafeWriteTo(ByteString, ByteOutput) |
| 691 */ | 679 */ |
| 692 abstract void writeTo(ByteOutput byteOutput) throws IOException; | 680 abstract void writeTo(ByteOutput byteOutput) throws IOException; |
| 693 | 681 |
| 694 | |
| 695 /** | 682 /** |
| 696 * Constructs a read-only {@code java.nio.ByteBuffer} whose content | 683 * Constructs a read-only {@code java.nio.ByteBuffer} whose content |
| 697 * is equal to the contents of this byte string. | 684 * is equal to the contents of this byte string. |
| 698 * The result uses the same backing array as the byte string, if possible. | 685 * The result uses the same backing array as the byte string, if possible. |
| 699 * | 686 * |
| 700 * @return wrapped bytes | 687 * @return wrapped bytes |
| 701 */ | 688 */ |
| 702 public abstract ByteBuffer asReadOnlyByteBuffer(); | 689 public abstract ByteBuffer asReadOnlyByteBuffer(); |
| 703 | 690 |
| 704 /** | 691 /** |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 826 @Override | 813 @Override |
| 827 protected final int getTreeDepth() { | 814 protected final int getTreeDepth() { |
| 828 return 0; | 815 return 0; |
| 829 } | 816 } |
| 830 | 817 |
| 831 @Override | 818 @Override |
| 832 protected final boolean isBalanced() { | 819 protected final boolean isBalanced() { |
| 833 return true; | 820 return true; |
| 834 } | 821 } |
| 835 | 822 |
| 836 | |
| 837 /** | 823 /** |
| 838 * Check equality of the substring of given length of this object starting a
t | 824 * Check equality of the substring of given length of this object starting a
t |
| 839 * zero with another {@code ByteString} substring starting at offset. | 825 * zero with another {@code ByteString} substring starting at offset. |
| 840 * | 826 * |
| 841 * @param other what to compare a substring in | 827 * @param other what to compare a substring in |
| 842 * @param offset offset into other | 828 * @param offset offset into other |
| 843 * @param length number of bytes to compare | 829 * @param length number of bytes to compare |
| 844 * @return true for equality of substrings, else false. | 830 * @return true for equality of substrings, else false. |
| 845 */ | 831 */ |
| 846 abstract boolean equalsRange(ByteString other, int offset, int length); | 832 abstract boolean equalsRange(ByteString other, int offset, int length); |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1233 throw new IndexOutOfBoundsException("End index: " + endIndex + " >= " + si
ze); | 1219 throw new IndexOutOfBoundsException("End index: " + endIndex + " >= " + si
ze); |
| 1234 } | 1220 } |
| 1235 return length; | 1221 return length; |
| 1236 } | 1222 } |
| 1237 | 1223 |
| 1238 @Override | 1224 @Override |
| 1239 public final String toString() { | 1225 public final String toString() { |
| 1240 return String.format("<ByteString@%s size=%d>", | 1226 return String.format("<ByteString@%s size=%d>", |
| 1241 Integer.toHexString(System.identityHashCode(this)), size()); | 1227 Integer.toHexString(System.identityHashCode(this)), size()); |
| 1242 } | 1228 } |
| 1243 | 1229 |
| 1244 /** | 1230 /** |
| 1245 * This class implements a {@link com.google.protobuf.ByteString} backed by a | 1231 * This class implements a {@link com.google.protobuf.ByteString} backed by a |
| 1246 * single array of bytes, contiguous in memory. It supports substring by | 1232 * single array of bytes, contiguous in memory. It supports substring by |
| 1247 * pointing to only a sub-range of the underlying byte array, meaning that a | 1233 * pointing to only a sub-range of the underlying byte array, meaning that a |
| 1248 * substring will reference the full byte-array of the string it's made from, | 1234 * substring will reference the full byte-array of the string it's made from, |
| 1249 * exactly as with {@link String}. | 1235 * exactly as with {@link String}. |
| 1250 * | 1236 * |
| 1251 * @author carlanton@google.com (Carl Haverl) | 1237 * @author carlanton@google.com (Carl Haverl) |
| 1252 */ | 1238 */ |
| 1253 // Keep this class private to avoid deadlocks in classloading across threads a
s ByteString's | 1239 // Keep this class private to avoid deadlocks in classloading across threads a
s ByteString's |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1457 | 1443 |
| 1458 /** | 1444 /** |
| 1459 * Offset into {@code bytes[]} to use, non-zero for substrings. | 1445 * Offset into {@code bytes[]} to use, non-zero for substrings. |
| 1460 * | 1446 * |
| 1461 * @return always 0 for this class | 1447 * @return always 0 for this class |
| 1462 */ | 1448 */ |
| 1463 protected int getOffsetIntoBytes() { | 1449 protected int getOffsetIntoBytes() { |
| 1464 return 0; | 1450 return 0; |
| 1465 } | 1451 } |
| 1466 } | 1452 } |
| 1467 | 1453 |
| 1468 /** | 1454 /** |
| 1469 * This class is used to represent the substring of a {@link ByteString} over
a | 1455 * This class is used to represent the substring of a {@link ByteString} over
a |
| 1470 * single byte array. In terms of the public API of {@link ByteString}, you en
d | 1456 * single byte array. In terms of the public API of {@link ByteString}, you en
d |
| 1471 * up here by calling {@link ByteString#copyFrom(byte[])} followed by {@link | 1457 * up here by calling {@link ByteString#copyFrom(byte[])} followed by {@link |
| 1472 * ByteString#substring(int, int)}. | 1458 * ByteString#substring(int, int)}. |
| 1473 * | 1459 * |
| 1474 * <p>This class contains most of the overhead involved in creating a substrin
g | 1460 * <p>This class contains most of the overhead involved in creating a substrin
g |
| 1475 * from a {@link LiteralByteString}. The overhead involves some range-checkin
g | 1461 * from a {@link LiteralByteString}. The overhead involves some range-checkin
g |
| 1476 * and two extra fields. | 1462 * and two extra fields. |
| 1477 * | 1463 * |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1549 Object writeReplace() { | 1535 Object writeReplace() { |
| 1550 return ByteString.wrap(toByteArray()); | 1536 return ByteString.wrap(toByteArray()); |
| 1551 } | 1537 } |
| 1552 | 1538 |
| 1553 private void readObject(@SuppressWarnings("unused") ObjectInputStream in) th
rows IOException { | 1539 private void readObject(@SuppressWarnings("unused") ObjectInputStream in) th
rows IOException { |
| 1554 throw new InvalidObjectException( | 1540 throw new InvalidObjectException( |
| 1555 "BoundedByteStream instances are not to be serialized directly"); | 1541 "BoundedByteStream instances are not to be serialized directly"); |
| 1556 } | 1542 } |
| 1557 } | 1543 } |
| 1558 } | 1544 } |
| OLD | NEW |