31
31
package com.google.protobuf;
33
import java.io.ByteArrayOutputStream;
34
import java.io.IOException;
33
35
import java.io.InputStream;
34
import java.io.ByteArrayInputStream;
35
import java.io.ByteArrayOutputStream;
36
import java.io.FilterOutputStream;
36
import java.io.OutputStream;
37
37
import java.io.UnsupportedEncodingException;
38
38
import java.nio.ByteBuffer;
39
import java.util.ArrayList;
40
import java.util.Collection;
41
import java.util.Iterator;
39
42
import java.util.List;
43
import java.util.NoSuchElementException;
42
* Immutable array of bytes.
46
* Immutable sequence of bytes. Substring is supported by sharing the reference
47
* to the immutable underlying bytes, as with {@link String}. Concatenation is
48
* likewise supported without copying (long strings) by building a tree of
49
* pieces in {@link RopeByteString}.
51
* Like {@link String}, the contents of a {@link ByteString} can never be
52
* observed to change, not even in the presence of a data race or incorrect
53
* API usage in the client code.
44
55
* @author crazybob@google.com Bob Lee
45
56
* @author kenton@google.com Kenton Varda
57
* @author carlanton@google.com Carl Haverl
58
* @author martinrb@google.com Martin Buchholz
47
public final class ByteString {
48
private final byte[] bytes;
50
private ByteString(final byte[] bytes) {
55
* Gets the byte at the given index.
60
public abstract class ByteString implements Iterable<Byte> {
63
* When two strings to be concatenated have a combined length shorter than
64
* this, we just copy their bytes on {@link #concat(ByteString)}.
65
* The trade-off is copy size versus the overhead of creating tree nodes
66
* in {@link RopeByteString}.
68
static final int CONCATENATE_BY_COPY_SIZE = 128;
71
* When copying an InputStream into a ByteString with .readFrom(),
72
* the chunks in the underlying rope start at 256 bytes, but double
73
* each iteration up to 8192 bytes.
75
static final int MIN_READ_FROM_CHUNK_SIZE = 0x100; // 256b
76
static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000; // 8k
79
* Empty {@code ByteString}.
81
public static final ByteString EMPTY = new LiteralByteString(new byte[0]);
83
// This constructor is here to prevent subclassing outside of this package,
87
* Gets the byte at the given index. This method should be used only for
88
* random access to individual bytes. To access bytes sequentially, use the
89
* {@link ByteIterator} returned by {@link #iterator()}, and call {@link
90
* #substring(int, int)} first if necessary.
92
* @param index index of byte
57
94
* @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
59
public byte byteAt(final int index) {
96
public abstract byte byteAt(int index);
99
* Return a {@link ByteString.ByteIterator} over the bytes in the ByteString.
100
* To avoid auto-boxing, you may get the iterator manually and call
101
* {@link ByteIterator#nextByte()}.
103
* @return the iterator
105
public abstract ByteIterator iterator();
108
* This interface extends {@code Iterator<Byte>}, so that we can return an
109
* unboxed {@code byte}.
111
public interface ByteIterator extends Iterator<Byte> {
113
* An alternative to {@link Iterator#next()} that returns an
114
* unboxed primitive {@code byte}.
116
* @return the next {@code byte} in the iteration
117
* @throws NoSuchElementException if the iteration has no more elements
64
123
* Gets the number of bytes.
125
* @return size in bytes
127
public abstract int size();
71
130
* Returns {@code true} if the size is {@code 0}, {@code false} otherwise.
132
* @return true if this is zero bytes long
73
134
public boolean isEmpty() {
74
return bytes.length == 0;
138
// =================================================================
139
// ByteString -> substring
142
* Return the substring from {@code beginIndex}, inclusive, to the end of the
145
* @param beginIndex start at this index
146
* @return substring sharing underlying data
147
* @throws IndexOutOfBoundsException if {@code beginIndex < 0} or
148
* {@code beginIndex > size()}.
150
public ByteString substring(int beginIndex) {
151
return substring(beginIndex, size());
155
* Return the substring from {@code beginIndex}, inclusive, to {@code
156
* endIndex}, exclusive.
158
* @param beginIndex start at this index
159
* @param endIndex the last character is the one before this index
160
* @return substring sharing underlying data
161
* @throws IndexOutOfBoundsException if {@code beginIndex < 0},
162
* {@code endIndex > size()}, or {@code beginIndex > endIndex}.
164
public abstract ByteString substring(int beginIndex, int endIndex);
167
* Tests if this bytestring starts with the specified prefix.
168
* Similar to {@link String#startsWith(String)}
170
* @param prefix the prefix.
171
* @return <code>true</code> if the byte sequence represented by the
172
* argument is a prefix of the byte sequence represented by
173
* this string; <code>false</code> otherwise.
175
public boolean startsWith(ByteString prefix) {
176
return size() >= prefix.size() &&
177
substring(0, prefix.size()).equals(prefix);
77
180
// =================================================================
78
181
// byte[] -> ByteString
83
public static final ByteString EMPTY = new ByteString(new byte[0]);
86
184
* Copies the given bytes into a {@code ByteString}.
186
* @param bytes source array
187
* @param offset offset in source array
188
* @param size number of bytes to copy
189
* @return new {@code ByteString}
88
public static ByteString copyFrom(final byte[] bytes, final int offset,
90
final byte[] copy = new byte[size];
191
public static ByteString copyFrom(byte[] bytes, int offset, int size) {
192
byte[] copy = new byte[size];
91
193
System.arraycopy(bytes, offset, copy, 0, size);
92
return new ByteString(copy);
194
return new LiteralByteString(copy);
96
198
* Copies the given bytes into a {@code ByteString}.
200
* @param bytes to copy
201
* @return new {@code ByteString}
98
public static ByteString copyFrom(final byte[] bytes) {
203
public static ByteString copyFrom(byte[] bytes) {
99
204
return copyFrom(bytes, 0, bytes.length);
103
* Copies {@code size} bytes from a {@code java.nio.ByteBuffer} into
208
* Copies the next {@code size} bytes from a {@code java.nio.ByteBuffer} into
104
209
* a {@code ByteString}.
211
* @param bytes source buffer
212
* @param size number of bytes to copy
213
* @return new {@code ByteString}
106
public static ByteString copyFrom(final ByteBuffer bytes, final int size) {
107
final byte[] copy = new byte[size];
215
public static ByteString copyFrom(ByteBuffer bytes, int size) {
216
byte[] copy = new byte[size];
109
return new ByteString(copy);
218
return new LiteralByteString(copy);
113
222
* Copies the remaining bytes from a {@code java.nio.ByteBuffer} into
114
223
* a {@code ByteString}.
225
* @param bytes sourceBuffer
226
* @return new {@code ByteString}
116
public static ByteString copyFrom(final ByteBuffer bytes) {
228
public static ByteString copyFrom(ByteBuffer bytes) {
117
229
return copyFrom(bytes, bytes.remaining());
121
233
* Encodes {@code text} into a sequence of bytes using the named charset
122
234
* and returns the result as a {@code ByteString}.
236
* @param text source string
237
* @param charsetName encoding to use
238
* @return new {@code ByteString}
239
* @throws UnsupportedEncodingException if the encoding isn't found
124
public static ByteString copyFrom(final String text, final String charsetName)
241
public static ByteString copyFrom(String text, String charsetName)
125
242
throws UnsupportedEncodingException {
126
return new ByteString(text.getBytes(charsetName));
243
return new LiteralByteString(text.getBytes(charsetName));
130
247
* Encodes {@code text} into a sequence of UTF-8 bytes and returns the
131
248
* result as a {@code ByteString}.
250
* @param text source string
251
* @return new {@code ByteString}
133
public static ByteString copyFromUtf8(final String text) {
253
public static ByteString copyFromUtf8(String text) {
135
return new ByteString(text.getBytes("UTF-8"));
255
return new LiteralByteString(text.getBytes("UTF-8"));
136
256
} catch (UnsupportedEncodingException e) {
137
257
throw new RuntimeException("UTF-8 not supported?", e);
142
* Concatenates all byte strings in the list and returns the result.
261
// =================================================================
262
// InputStream -> ByteString
265
* Completely reads the given stream's bytes into a
266
* {@code ByteString}, blocking if necessary until all bytes are
267
* read through to the end of the stream.
269
* <b>Performance notes:</b> The returned {@code ByteString} is an
270
* immutable tree of byte arrays ("chunks") of the stream data. The
271
* first chunk is small, with subsequent chunks each being double
272
* the size, up to 8K. If the caller knows the precise length of
273
* the stream and wishes to avoid all unnecessary copies and
274
* allocations, consider using the two-argument version of this
277
* @param streamToDrain The source stream, which is read completely
279
* @return A new {@code ByteString} which is made up of chunks of
280
* various sizes, depending on the behavior of the underlying
282
* @throws IOException IOException is thrown if there is a problem
283
* reading the underlying stream.
285
public static ByteString readFrom(InputStream streamToDrain)
288
streamToDrain, MIN_READ_FROM_CHUNK_SIZE, MAX_READ_FROM_CHUNK_SIZE);
292
* Completely reads the given stream's bytes into a
293
* {@code ByteString}, blocking if necessary until all bytes are
294
* read through to the end of the stream.
296
* <b>Performance notes:</b> The returned {@code ByteString} is an
297
* immutable tree of byte arrays ("chunks") of the stream data. The
298
* chunkSize parameter sets the size of these byte arrays. In
299
* particular, if the chunkSize is precisely the same as the length
300
* of the stream, unnecessary allocations and copies will be
301
* avoided. Otherwise, the chunks will be of the given size, except
302
* for the last chunk, which will be resized (via a reallocation and
303
* copy) to contain the remainder of the stream.
305
* @param streamToDrain The source stream, which is read completely
307
* @param chunkSize The size of the chunks in which to read the
309
* @return A new {@code ByteString} which is made up of chunks of
311
* @throws IOException IOException is thrown if there is a problem
312
* reading the underlying stream.
314
public static ByteString readFrom(InputStream streamToDrain, int chunkSize)
316
return readFrom(streamToDrain, chunkSize, chunkSize);
319
// Helper method that takes the chunk size range as a parameter.
320
public static ByteString readFrom(InputStream streamToDrain, int minChunkSize,
321
int maxChunkSize) throws IOException {
322
Collection<ByteString> results = new ArrayList<ByteString>();
324
// copy the inbound bytes into a list of chunks; the chunk size
325
// grows exponentially to support both short and long streams.
326
int chunkSize = minChunkSize;
328
ByteString chunk = readChunk(streamToDrain, chunkSize);
333
chunkSize = Math.min(chunkSize * 2, maxChunkSize);
336
return ByteString.copyFrom(results);
340
* Blocks until a chunk of the given size can be made from the
341
* stream, or EOF is reached. Calls read() repeatedly in case the
342
* given stream implementation doesn't completely fill the given
343
* buffer in one read() call.
345
* @return A chunk of the desired size, or else a chunk as large as
346
* was available when end of stream was reached. Returns null if the
347
* given stream had no more data in it.
349
private static ByteString readChunk(InputStream in, final int chunkSize)
351
final byte[] buf = new byte[chunkSize];
353
while (bytesRead < chunkSize) {
354
final int count = in.read(buf, bytesRead, chunkSize - bytesRead);
361
if (bytesRead == 0) {
364
return ByteString.copyFrom(buf, 0, bytesRead);
368
// =================================================================
369
// Multiple ByteStrings -> One ByteString
372
* Concatenate the given {@code ByteString} to this one. Short concatenations,
373
* of total size smaller than {@link ByteString#CONCATENATE_BY_COPY_SIZE}, are
374
* produced by copying the underlying bytes (as per Rope.java, <a
375
* href="http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol25/issue12/spe986.pdf">
376
* BAP95 </a>. In general, the concatenate involves no copying.
378
* @param other string to concatenate
379
* @return a new {@code ByteString} instance
381
public ByteString concat(ByteString other) {
382
int thisSize = size();
383
int otherSize = other.size();
384
if ((long) thisSize + otherSize >= Integer.MAX_VALUE) {
385
throw new IllegalArgumentException("ByteString would be too long: " +
386
thisSize + "+" + otherSize);
389
return RopeByteString.concatenate(this, other);
393
* Concatenates all byte strings in the iterable and returns the result.
394
* This is designed to run in O(list size), not O(total bytes).
144
396
* <p>The returned {@code ByteString} is not necessarily a unique object.
145
397
* If the list is empty, the returned object is the singleton empty
146
398
* {@code ByteString}. If the list has only one element, that
147
399
* {@code ByteString} will be returned without copying.
401
* @param byteStrings strings to be concatenated
402
* @return new {@code ByteString}
149
public static ByteString copyFrom(List<ByteString> list) {
150
if (list.size() == 0) {
152
} else if (list.size() == 1) {
404
public static ByteString copyFrom(Iterable<ByteString> byteStrings) {
405
Collection<ByteString> collection;
406
if (!(byteStrings instanceof Collection)) {
407
collection = new ArrayList<ByteString>();
408
for (ByteString byteString : byteStrings) {
409
collection.add(byteString);
412
collection = (Collection<ByteString>) byteStrings;
415
if (collection.isEmpty()) {
418
result = balancedConcat(collection.iterator(), collection.size());
157
for (ByteString str : list) {
160
byte[] bytes = new byte[size];
162
for (ByteString str : list) {
163
System.arraycopy(str.bytes, 0, bytes, pos, str.size());
166
return new ByteString(bytes);
423
// Internal function used by copyFrom(Iterable<ByteString>).
424
// Create a balanced concatenation of the next "length" elements from the
426
private static ByteString balancedConcat(Iterator<ByteString> iterator,
431
result = iterator.next();
433
int halfLength = length >>> 1;
434
ByteString left = balancedConcat(iterator, halfLength);
435
ByteString right = balancedConcat(iterator, length - halfLength);
436
result = left.concat(right);
169
441
// =================================================================
175
447
* @param target buffer to copy into
176
448
* @param offset in the target buffer
449
* @throws IndexOutOfBoundsException if the offset is negative or too large
178
public void copyTo(final byte[] target, final int offset) {
179
System.arraycopy(bytes, 0, target, offset, bytes.length);
451
public void copyTo(byte[] target, int offset) {
452
copyTo(target, 0, offset, size());
183
456
* Copies bytes into a buffer.
185
* @param target buffer to copy into
458
* @param target buffer to copy into
186
459
* @param sourceOffset offset within these bytes
187
460
* @param targetOffset offset within the target buffer
188
* @param size number of bytes to copy
461
* @param numberToCopy number of bytes to copy
462
* @throws IndexOutOfBoundsException if an offset or size is negative or too
190
public void copyTo(final byte[] target, final int sourceOffset,
191
final int targetOffset,
193
System.arraycopy(bytes, sourceOffset, target, targetOffset, size);
465
public void copyTo(byte[] target, int sourceOffset, int targetOffset,
467
if (sourceOffset < 0) {
468
throw new IndexOutOfBoundsException("Source offset < 0: " + sourceOffset);
470
if (targetOffset < 0) {
471
throw new IndexOutOfBoundsException("Target offset < 0: " + targetOffset);
473
if (numberToCopy < 0) {
474
throw new IndexOutOfBoundsException("Length < 0: " + numberToCopy);
476
if (sourceOffset + numberToCopy > size()) {
477
throw new IndexOutOfBoundsException(
478
"Source end offset < 0: " + (sourceOffset + numberToCopy));
480
if (targetOffset + numberToCopy > target.length) {
481
throw new IndexOutOfBoundsException(
482
"Target end offset < 0: " + (targetOffset + numberToCopy));
484
if (numberToCopy > 0) {
485
copyToInternal(target, sourceOffset, targetOffset, numberToCopy);
490
* Internal (package private) implementation of
491
* @link{#copyTo(byte[],int,int,int}.
492
* It assumes that all error checking has already been performed and that
493
* @code{numberToCopy > 0}.
495
protected abstract void copyToInternal(byte[] target, int sourceOffset,
496
int targetOffset, int numberToCopy);
197
499
* Copies bytes into a ByteBuffer.
199
501
* @param target ByteBuffer to copy into.
200
* @throws ReadOnlyBufferException if the {@code target} is read-only
201
* @throws BufferOverflowException if the {@code target}'s remaining()
202
* space is not large enough to hold the data.
502
* @throws java.nio.ReadOnlyBufferException if the {@code target} is read-only
503
* @throws java.nio.BufferOverflowException if the {@code target}'s
504
* remaining() space is not large enough to hold the data.
204
public void copyTo(ByteBuffer target) {
205
target.put(bytes, 0, bytes.length);
506
public abstract void copyTo(ByteBuffer target);
209
509
* Copies bytes to a {@code byte[]}.
511
* @return copied bytes
211
513
public byte[] toByteArray() {
212
final int size = bytes.length;
213
final byte[] copy = new byte[size];
214
System.arraycopy(bytes, 0, copy, 0, size);
219
* Constructs a new read-only {@code java.nio.ByteBuffer} with the
220
* same backing byte array.
222
public ByteBuffer asReadOnlyByteBuffer() {
223
final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
224
return byteBuffer.asReadOnlyBuffer();
515
byte[] result = new byte[size];
516
copyToInternal(result, 0, 0, size);
521
* Writes the complete contents of this byte string to
522
* the specified output stream argument.
524
* @param out the output stream to which to write the data.
525
* @throws IOException if an I/O error occurs.
527
public abstract void writeTo(OutputStream out) throws IOException;
530
* Constructs a read-only {@code java.nio.ByteBuffer} whose content
531
* is equal to the contents of this byte string.
532
* The result uses the same backing array as the byte string, if possible.
534
* @return wrapped bytes
536
public abstract ByteBuffer asReadOnlyByteBuffer();
539
* Constructs a list of read-only {@code java.nio.ByteBuffer} objects
540
* such that the concatenation of their contents is equal to the contents
541
* of this byte string. The result uses the same backing arrays as the
544
* By returning a list, implementations of this method may be able to avoid
545
* copying even when there are multiple backing arrays.
547
* @return a list of wrapped bytes
549
public abstract List<ByteBuffer> asReadOnlyByteBufferList();
228
552
* Constructs a new {@code String} by decoding the bytes using the
229
553
* specified charset.
555
* @param charsetName encode using this charset
557
* @throws UnsupportedEncodingException if charset isn't recognized
231
public String toString(final String charsetName)
232
throws UnsupportedEncodingException {
233
return new String(bytes, charsetName);
559
public abstract String toString(String charsetName)
560
throws UnsupportedEncodingException;
562
// =================================================================
237
566
* Constructs a new {@code String} by decoding the bytes as UTF-8.
568
* @return new string using UTF-8 encoding
239
570
public String toStringUtf8() {
241
return new String(bytes, "UTF-8");
572
return toString("UTF-8");
242
573
} catch (UnsupportedEncodingException e) {
243
574
throw new RuntimeException("UTF-8 not supported?", e);
579
* Tells whether this {@code ByteString} represents a well-formed UTF-8
580
* byte sequence, such that the original bytes can be converted to a
581
* String object and then round tripped back to bytes without loss.
583
* <p>More precisely, returns {@code true} whenever: <pre> {@code
584
* Arrays.equals(byteString.toByteArray(),
585
* new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
588
* <p>This method returns {@code false} for "overlong" byte sequences,
589
* as well as for 3-byte sequences that would map to a surrogate
590
* character, in accordance with the restricted definition of UTF-8
591
* introduced in Unicode 3.1. Note that the UTF-8 decoder included in
592
* Oracle's JDK has been modified to also reject "overlong" byte
593
* sequences, but (as of 2011) still accepts 3-byte surrogate
594
* character byte sequences.
596
* <p>See the Unicode Standard,</br>
597
* Table 3-6. <em>UTF-8 Bit Distribution</em>,</br>
598
* Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
600
* @return whether the bytes in this {@code ByteString} are a
601
* well-formed UTF-8 byte sequence
603
public abstract boolean isValidUtf8();
606
* Tells whether the given byte sequence is a well-formed, malformed, or
607
* incomplete UTF-8 byte sequence. This method accepts and returns a partial
608
* state result, allowing the bytes for a complete UTF-8 byte sequence to be
609
* composed from multiple {@code ByteString} segments.
611
* @param state either {@code 0} (if this is the initial decoding operation)
612
* or the value returned from a call to a partial decoding method for the
614
* @param offset offset of the first byte to check
615
* @param length number of bytes to check
617
* @return {@code -1} if the partial byte sequence is definitely malformed,
618
* {@code 0} if it is well-formed (no additional input needed), or, if the
619
* byte sequence is "incomplete", i.e. apparently terminated in the middle of
620
* a character, an opaque integer "state" value containing enough information
621
* to decode the character when passed to a subsequent invocation of a
622
* partial decoding method.
624
protected abstract int partialIsValidUtf8(int state, int offset, int length);
247
626
// =================================================================
248
627
// equals() and hashCode()
251
public boolean equals(final Object o) {
256
if (!(o instanceof ByteString)) {
260
final ByteString other = (ByteString) o;
261
final int size = bytes.length;
262
if (size != other.bytes.length) {
266
final byte[] thisBytes = bytes;
267
final byte[] otherBytes = other.bytes;
268
for (int i = 0; i < size; i++) {
269
if (thisBytes[i] != otherBytes[i]) {
277
private volatile int hash = 0;
630
public abstract boolean equals(Object o);
633
* Return a non-zero hashCode depending only on the sequence of bytes
634
* in this ByteString.
636
* @return hashCode value for this object
280
public int hashCode() {
284
final byte[] thisBytes = bytes;
285
final int size = bytes.length;
288
for (int i = 0; i < size; i++) {
289
h = h * 31 + thisBytes[i];
639
public abstract int hashCode();
301
641
// =================================================================
305
645
* Creates an {@code InputStream} which can be used to read the bytes.
647
* The {@link InputStream} returned by this method is guaranteed to be
648
* completely non-blocking. The method {@link InputStream#available()}
649
* returns the number of bytes remaining in the stream. The methods
650
* {@link InputStream#read(byte[]), {@link InputStream#read(byte[],int,int)}
651
* and {@link InputStream#skip(long)} will read/skip as many bytes as are
654
* The methods in the returned {@link InputStream} might <b>not</b> be
657
* @return an input stream that returns the bytes of this byte string.
307
public InputStream newInput() {
308
return new ByteArrayInputStream(bytes);
659
public abstract InputStream newInput();
312
662
* Creates a {@link CodedInputStream} which can be used to read the bytes.
313
* Using this is more efficient than creating a {@link CodedInputStream}
314
* wrapping the result of {@link #newInput()}.
663
* Using this is often more efficient than creating a {@link CodedInputStream}
664
* that wraps the result of {@link #newInput()}.
666
* @return stream based on wrapped data
316
public CodedInputStream newCodedInput() {
317
// We trust CodedInputStream not to modify the bytes, or to give anyone
318
// else access to them.
319
return CodedInputStream.newInstance(bytes);
668
public abstract CodedInputStream newCodedInput();
322
670
// =================================================================
326
* Creates a new {@link Output} with the given initial capacity.
674
* Creates a new {@link Output} with the given initial capacity. Call {@link
675
* Output#toByteString()} to create the {@code ByteString} instance.
677
* A {@link ByteString.Output} offers the same functionality as a
678
* {@link ByteArrayOutputStream}, except that it returns a {@link ByteString}
679
* rather than a {@code byte} array.
681
* @param initialCapacity estimate of number of bytes to be written
682
* @return {@code OutputStream} for building a {@code ByteString}
328
public static Output newOutput(final int initialCapacity) {
329
return new Output(new ByteArrayOutputStream(initialCapacity));
684
public static Output newOutput(int initialCapacity) {
685
return new Output(initialCapacity);
333
* Creates a new {@link Output}.
689
* Creates a new {@link Output}. Call {@link Output#toByteString()} to create
690
* the {@code ByteString} instance.
692
* A {@link ByteString.Output} offers the same functionality as a
693
* {@link ByteArrayOutputStream}, except that it returns a {@link ByteString}
694
* rather than a {@code byte array}.
696
* @return {@code OutputStream} for building a {@code ByteString}
335
698
public static Output newOutput() {
336
return newOutput(32);
699
return new Output(CONCATENATE_BY_COPY_SIZE);
340
703
* Outputs to a {@code ByteString} instance. Call {@link #toByteString()} to
341
704
* create the {@code ByteString} instance.
343
public static final class Output extends FilterOutputStream {
344
private final ByteArrayOutputStream bout;
347
* Constructs a new output with the given initial capacity.
349
private Output(final ByteArrayOutputStream bout) {
355
* Creates a {@code ByteString} instance from this {@code Output}.
357
public ByteString toByteString() {
358
final byte[] byteArray = bout.toByteArray();
359
return new ByteString(byteArray);
706
public static final class Output extends OutputStream {
707
// Implementation note.
708
// The public methods of this class must be synchronized. ByteStrings
709
// are guaranteed to be immutable. Without some sort of locking, it could
710
// be possible for one thread to call toByteSring(), while another thread
711
// is still modifying the underlying byte array.
713
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
714
// argument passed by user, indicating initial capacity.
715
private final int initialCapacity;
716
// ByteStrings to be concatenated to create the result
717
private final ArrayList<ByteString> flushedBuffers;
718
// Total number of bytes in the ByteStrings of flushedBuffers
719
private int flushedBuffersTotalBytes;
720
// Current buffer to which we are writing
721
private byte[] buffer;
722
// Location in buffer[] to which we write the next byte.
723
private int bufferPos;
726
* Creates a new ByteString output stream with the specified
729
* @param initialCapacity the initial capacity of the output stream.
731
Output(int initialCapacity) {
732
if (initialCapacity < 0) {
733
throw new IllegalArgumentException("Buffer size < 0");
735
this.initialCapacity = initialCapacity;
736
this.flushedBuffers = new ArrayList<ByteString>();
737
this.buffer = new byte[initialCapacity];
741
public synchronized void write(int b) {
742
if (bufferPos == buffer.length) {
745
buffer[bufferPos++] = (byte)b;
749
public synchronized void write(byte[] b, int offset, int length) {
750
if (length <= buffer.length - bufferPos) {
751
// The bytes can fit into the current buffer.
752
System.arraycopy(b, offset, buffer, bufferPos, length);
755
// Use up the current buffer
756
int copySize = buffer.length - bufferPos;
757
System.arraycopy(b, offset, buffer, bufferPos, copySize);
760
// Flush the buffer, and get a new buffer at least big enough to cover
761
// what we still need to output
762
flushFullBuffer(length);
763
System.arraycopy(b, offset, buffer, 0 /* count */, length);
769
* Creates a byte string. Its size is the current size of this output
770
* stream and its output has been copied to it.
772
* @return the current contents of this output stream, as a byte string.
774
public synchronized ByteString toByteString() {
776
return ByteString.copyFrom(flushedBuffers);
780
* Implement java.util.Arrays.copyOf() for jdk 1.5.
782
private byte[] copyArray(byte[] buffer, int length) {
783
byte[] result = new byte[length];
784
System.arraycopy(buffer, 0, result, 0, Math.min(buffer.length, length));
789
* Writes the complete contents of this byte array output stream to
790
* the specified output stream argument.
792
* @param out the output stream to which to write the data.
793
* @throws IOException if an I/O error occurs.
795
public void writeTo(OutputStream out) throws IOException {
796
ByteString[] cachedFlushBuffers;
799
synchronized (this) {
800
// Copy the information we need into local variables so as to hold
801
// the lock for as short a time as possible.
803
flushedBuffers.toArray(new ByteString[flushedBuffers.size()]);
804
cachedBuffer = buffer;
805
cachedBufferPos = bufferPos;
807
for (ByteString byteString : cachedFlushBuffers) {
808
byteString.writeTo(out);
811
out.write(copyArray(cachedBuffer, cachedBufferPos));
815
* Returns the current size of the output stream.
817
* @return the current size of the output stream
819
public synchronized int size() {
820
return flushedBuffersTotalBytes + bufferPos;
824
* Resets this stream, so that all currently accumulated output in the
825
* output stream is discarded. The output stream can be used again,
826
* reusing the already allocated buffer space.
828
public synchronized void reset() {
829
flushedBuffers.clear();
830
flushedBuffersTotalBytes = 0;
835
public String toString() {
836
return String.format("<ByteString.Output@%s size=%d>",
837
Integer.toHexString(System.identityHashCode(this)), size());
841
* Internal function used by writers. The current buffer is full, and the
842
* writer needs a new buffer whose size is at least the specified minimum
845
private void flushFullBuffer(int minSize) {
846
flushedBuffers.add(new LiteralByteString(buffer));
847
flushedBuffersTotalBytes += buffer.length;
848
// We want to increase our total capacity by 50%, but as a minimum,
849
// the new buffer should also at least be >= minSize and
850
// >= initial Capacity.
851
int newSize = Math.max(initialCapacity,
852
Math.max(minSize, flushedBuffersTotalBytes >>> 1));
853
buffer = new byte[newSize];
858
* Internal function used by {@link #toByteString()}. The current buffer may
859
* or may not be full, but it needs to be flushed.
861
private void flushLastBuffer() {
862
if (bufferPos < buffer.length) {
864
byte[] bufferCopy = copyArray(buffer, bufferPos);
865
flushedBuffers.add(new LiteralByteString(bufferCopy));
867
// We reuse this buffer for further writes.
869
// Buffer is completely full. Huzzah.
870
flushedBuffers.add(new LiteralByteString(buffer));
871
// 99% of the time, we're not going to use this OutputStream again.
872
// We set buffer to an empty byte stream so that we're handling this
873
// case without wasting space. In the rare case that more writes
874
// *do* occur, this empty buffer will be flushed and an appropriately
875
// sized new buffer will be created.
876
buffer = EMPTY_BYTE_ARRAY;
878
flushedBuffersTotalBytes += bufferPos;
364
* Constructs a new ByteString builder, which allows you to efficiently
365
* construct a {@code ByteString} by writing to a {@link CodedOutputStream}.
366
* Using this is much more efficient than calling {@code newOutput()} and
367
* wrapping that in a {@code CodedOutputStream}.
884
* Constructs a new {@code ByteString} builder, which allows you to
885
* efficiently construct a {@code ByteString} by writing to a {@link
886
* CodedOutputStream}. Using this is much more efficient than calling {@code
887
* newOutput()} and wrapping that in a {@code CodedOutputStream}.
369
889
* <p>This is package-private because it's a somewhat confusing interface.
370
890
* Users can call {@link Message#toByteString()} instead of calling this
373
* @param size The target byte size of the {@code ByteString}. You must
374
* write exactly this many bytes before building the result.
893
* @param size The target byte size of the {@code ByteString}. You must write
894
* exactly this many bytes before building the result.
895
* @return the builder
376
static CodedBuilder newCodedBuilder(final int size) {
897
static CodedBuilder newCodedBuilder(int size) {
377
898
return new CodedBuilder(size);