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 |