1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
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
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.
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.
31 package com.google.protobuf;
33 import java.io.ByteArrayOutputStream;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.nio.ByteBuffer;
37 import java.util.ArrayList;
38 import java.util.Arrays;
39 import java.util.List;
42 * Reads and decodes protocol message fields.
44 * This class contains two kinds of methods: methods that read specific
45 * protocol message constructs and field types (e.g. {@link #readTag()} and
46 * {@link #readInt32()}) and methods that read low-level values (e.g.
47 * {@link #readRawVarint32()} and {@link #readRawBytes}). If you are reading
48 * encoded protocol messages, you should use the former methods, but if you are
49 * reading some other format of your own design, use the latter.
51 * @author kenton@google.com Kenton Varda
53 public final class CodedInputStream {
55 * Create a new CodedInputStream wrapping the given InputStream.
57 public static CodedInputStream newInstance(final InputStream input) {
58 return new CodedInputStream(input);
62 * Create a new CodedInputStream wrapping the given byte array.
64 public static CodedInputStream newInstance(final byte[] buf) {
65 return newInstance(buf, 0, buf.length);
69 * Create a new CodedInputStream wrapping the given byte array slice.
71 public static CodedInputStream newInstance(final byte[] buf, final int off,
73 CodedInputStream result = new CodedInputStream(buf, off, len);
75 // Some uses of CodedInputStream can be more efficient if they know
76 // exactly how many bytes are available. By pushing the end point of the
77 // buffer as a limit, we allow them to get this information via
78 // getBytesUntilLimit(). Pushing a limit that we know is at the end of
79 // the stream can never hurt, since we can never past that point anyway.
80 result.pushLimit(len);
81 } catch (InvalidProtocolBufferException ex) {
82 // The only reason pushLimit() might throw an exception here is if len
83 // is negative. Normally pushLimit()'s parameter comes directly off the
84 // wire, so it's important to catch exceptions in case of corrupt or
85 // malicious data. However, in this case, we expect that len is not a
86 // user-supplied value, so we can assume that it being negative indicates
87 // a programming error. Therefore, throwing an unchecked exception is
89 throw new IllegalArgumentException(ex);
95 * Create a new CodedInputStream wrapping the given ByteBuffer. The data
96 * starting from the ByteBuffer's current position to its limit will be read.
97 * The returned CodedInputStream may or may not share the underlying data
98 * in the ByteBuffer, therefore the ByteBuffer cannot be changed while the
99 * CodedInputStream is in use.
100 * Note that the ByteBuffer's position won't be changed by this function.
101 * Concurrent calls with the same ByteBuffer object are safe if no other
102 * thread is trying to alter the ByteBuffer's status.
104 public static CodedInputStream newInstance(ByteBuffer buf) {
105 if (buf.hasArray()) {
106 return newInstance(buf.array(), buf.arrayOffset() + buf.position(),
109 ByteBuffer temp = buf.duplicate();
110 byte[] buffer = new byte[temp.remaining()];
112 return newInstance(buffer);
117 * Create a new CodedInputStream wrapping a LiteralByteString.
119 static CodedInputStream newInstance(LiteralByteString byteString) {
120 CodedInputStream result = new CodedInputStream(byteString);
122 // Some uses of CodedInputStream can be more efficient if they know
123 // exactly how many bytes are available. By pushing the end point of the
124 // buffer as a limit, we allow them to get this information via
125 // getBytesUntilLimit(). Pushing a limit that we know is at the end of
126 // the stream can never hurt, since we can never past that point anyway.
127 result.pushLimit(byteString.size());
128 } catch (InvalidProtocolBufferException ex) {
129 // The only reason pushLimit() might throw an exception here is if len
130 // is negative. Normally pushLimit()'s parameter comes directly off the
131 // wire, so it's important to catch exceptions in case of corrupt or
132 // malicious data. However, in this case, we expect that len is not a
133 // user-supplied value, so we can assume that it being negative indicates
134 // a programming error. Therefore, throwing an unchecked exception is
136 throw new IllegalArgumentException(ex);
141 // -----------------------------------------------------------------
144 * Attempt to read a field tag, returning zero if we have reached EOF.
145 * Protocol message parsers use this to read tags, since a protocol message
146 * may legally end wherever a tag occurs, and zero is not a valid tag number.
148 public int readTag() throws IOException {
154 lastTag = readRawVarint32();
155 if (WireFormat.getTagFieldNumber(lastTag) == 0) {
156 // If we actually read zero (or any tag number corresponding to field
157 // number zero), that's not a valid tag.
158 throw InvalidProtocolBufferException.invalidTag();
164 * Verifies that the last call to readTag() returned the given tag value.
165 * This is used to verify that a nested group ended with the correct
168 * @throws InvalidProtocolBufferException {@code value} does not match the
171 public void checkLastTagWas(final int value)
172 throws InvalidProtocolBufferException {
173 if (lastTag != value) {
174 throw InvalidProtocolBufferException.invalidEndTag();
178 public int getLastTag() {
183 * Reads and discards a single field, given its tag value.
185 * @return {@code false} if the tag is an endgroup tag, in which case
186 * nothing is skipped. Otherwise, returns {@code true}.
188 public boolean skipField(final int tag) throws IOException {
189 switch (WireFormat.getTagWireType(tag)) {
190 case WireFormat.WIRETYPE_VARINT:
193 case WireFormat.WIRETYPE_FIXED64:
196 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
197 skipRawBytes(readRawVarint32());
199 case WireFormat.WIRETYPE_START_GROUP:
202 WireFormat.makeTag(WireFormat.getTagFieldNumber(tag),
203 WireFormat.WIRETYPE_END_GROUP));
205 case WireFormat.WIRETYPE_END_GROUP:
207 case WireFormat.WIRETYPE_FIXED32:
211 throw InvalidProtocolBufferException.invalidWireType();
216 * Reads a single field and writes it to output in wire format,
217 * given its tag value.
219 * @return {@code false} if the tag is an endgroup tag, in which case
220 * nothing is skipped. Otherwise, returns {@code true}.
222 public boolean skipField(final int tag, final CodedOutputStream output)
224 switch (WireFormat.getTagWireType(tag)) {
225 case WireFormat.WIRETYPE_VARINT: {
226 long value = readInt64();
227 output.writeRawVarint32(tag);
228 output.writeUInt64NoTag(value);
231 case WireFormat.WIRETYPE_FIXED64: {
232 long value = readRawLittleEndian64();
233 output.writeRawVarint32(tag);
234 output.writeFixed64NoTag(value);
237 case WireFormat.WIRETYPE_LENGTH_DELIMITED: {
238 ByteString value = readBytes();
239 output.writeRawVarint32(tag);
240 output.writeBytesNoTag(value);
243 case WireFormat.WIRETYPE_START_GROUP: {
244 output.writeRawVarint32(tag);
246 int endtag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag),
247 WireFormat.WIRETYPE_END_GROUP);
248 checkLastTagWas(endtag);
249 output.writeRawVarint32(endtag);
252 case WireFormat.WIRETYPE_END_GROUP: {
255 case WireFormat.WIRETYPE_FIXED32: {
256 int value = readRawLittleEndian32();
257 output.writeRawVarint32(tag);
258 output.writeFixed32NoTag(value);
262 throw InvalidProtocolBufferException.invalidWireType();
267 * Reads and discards an entire message. This will read either until EOF
268 * or until an endgroup tag, whichever comes first.
270 public void skipMessage() throws IOException {
272 final int tag = readTag();
273 if (tag == 0 || !skipField(tag)) {
280 * Reads an entire message and writes it to output in wire format.
281 * This will read either until EOF or until an endgroup tag,
282 * whichever comes first.
284 public void skipMessage(CodedOutputStream output) throws IOException {
286 final int tag = readTag();
287 if (tag == 0 || !skipField(tag, output)) {
294 * Collects the bytes skipped and returns the data in a ByteBuffer.
296 private class SkippedDataSink implements RefillCallback {
297 private int lastPos = bufferPos;
298 private ByteArrayOutputStream byteArrayStream;
301 public void onRefill() {
302 if (byteArrayStream == null) {
303 byteArrayStream = new ByteArrayOutputStream();
305 byteArrayStream.write(buffer, lastPos, bufferPos - lastPos);
310 * Gets skipped data in a ByteBuffer. This method should only be
313 ByteBuffer getSkippedData() {
314 if (byteArrayStream == null) {
315 return ByteBuffer.wrap(buffer, lastPos, bufferPos - lastPos);
317 byteArrayStream.write(buffer, lastPos, bufferPos);
318 return ByteBuffer.wrap(byteArrayStream.toByteArray());
324 // -----------------------------------------------------------------
326 /** Read a {@code double} field value from the stream. */
327 public double readDouble() throws IOException {
328 return Double.longBitsToDouble(readRawLittleEndian64());
331 /** Read a {@code float} field value from the stream. */
332 public float readFloat() throws IOException {
333 return Float.intBitsToFloat(readRawLittleEndian32());
336 /** Read a {@code uint64} field value from the stream. */
337 public long readUInt64() throws IOException {
338 return readRawVarint64();
341 /** Read an {@code int64} field value from the stream. */
342 public long readInt64() throws IOException {
343 return readRawVarint64();
346 /** Read an {@code int32} field value from the stream. */
347 public int readInt32() throws IOException {
348 return readRawVarint32();
351 /** Read a {@code fixed64} field value from the stream. */
352 public long readFixed64() throws IOException {
353 return readRawLittleEndian64();
356 /** Read a {@code fixed32} field value from the stream. */
357 public int readFixed32() throws IOException {
358 return readRawLittleEndian32();
361 /** Read a {@code bool} field value from the stream. */
362 public boolean readBool() throws IOException {
363 return readRawVarint64() != 0;
367 * Read a {@code string} field value from the stream.
368 * If the stream contains malformed UTF-8,
369 * replace the offending bytes with the standard UTF-8 replacement character.
371 public String readString() throws IOException {
372 final int size = readRawVarint32();
373 if (size <= (bufferSize - bufferPos) && size > 0) {
374 // Fast path: We already have the bytes in a contiguous buffer, so
375 // just copy directly from it.
376 final String result = new String(buffer, bufferPos, size, "UTF-8");
379 } else if (size == 0) {
382 // Slow path: Build a byte array first then copy it.
383 return new String(readRawBytesSlowPath(size), "UTF-8");
388 * Read a {@code string} field value from the stream.
389 * If the stream contains malformed UTF-8,
390 * throw exception {@link InvalidProtocolBufferException}.
392 public String readStringRequireUtf8() throws IOException {
393 final int size = readRawVarint32();
396 if (size <= (bufferSize - pos) && size > 0) {
397 // Fast path: We already have the bytes in a contiguous buffer, so
398 // just copy directly from it.
400 bufferPos = pos + size;
401 } else if (size == 0) {
404 // Slow path: Build a byte array first then copy it.
405 bytes = readRawBytesSlowPath(size);
408 // TODO(martinrb): We could save a pass by validating while decoding.
409 if (!Utf8.isValidUtf8(bytes, pos, pos + size)) {
410 throw InvalidProtocolBufferException.invalidUtf8();
412 return new String(bytes, pos, size, "UTF-8");
415 /** Read a {@code group} field value from the stream. */
416 public void readGroup(final int fieldNumber,
417 final MessageLite.Builder builder,
418 final ExtensionRegistryLite extensionRegistry)
420 if (recursionDepth >= recursionLimit) {
421 throw InvalidProtocolBufferException.recursionLimitExceeded();
424 builder.mergeFrom(this, extensionRegistry);
426 WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
431 /** Read a {@code group} field value from the stream. */
432 public <T extends MessageLite> T readGroup(
433 final int fieldNumber,
434 final Parser<T> parser,
435 final ExtensionRegistryLite extensionRegistry)
437 if (recursionDepth >= recursionLimit) {
438 throw InvalidProtocolBufferException.recursionLimitExceeded();
441 T result = parser.parsePartialFrom(this, extensionRegistry);
443 WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
449 * Reads a {@code group} field value from the stream and merges it into the
450 * given {@link UnknownFieldSet}.
452 * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so
453 * you can just call {@link #readGroup}.
456 public void readUnknownGroup(final int fieldNumber,
457 final MessageLite.Builder builder)
459 // We know that UnknownFieldSet will ignore any ExtensionRegistry so it
460 // is safe to pass null here. (We can't call
461 // ExtensionRegistry.getEmptyRegistry() because that would make this
462 // class depend on ExtensionRegistry, which is not part of the lite
464 readGroup(fieldNumber, builder, null);
467 /** Read an embedded message field value from the stream. */
468 public void readMessage(final MessageLite.Builder builder,
469 final ExtensionRegistryLite extensionRegistry)
471 final int length = readRawVarint32();
472 if (recursionDepth >= recursionLimit) {
473 throw InvalidProtocolBufferException.recursionLimitExceeded();
475 final int oldLimit = pushLimit(length);
477 builder.mergeFrom(this, extensionRegistry);
484 /** Read an embedded message field value from the stream. */
485 public <T extends MessageLite> T readMessage(
486 final Parser<T> parser,
487 final ExtensionRegistryLite extensionRegistry)
489 int length = readRawVarint32();
490 if (recursionDepth >= recursionLimit) {
491 throw InvalidProtocolBufferException.recursionLimitExceeded();
493 final int oldLimit = pushLimit(length);
495 T result = parser.parsePartialFrom(this, extensionRegistry);
502 /** Read a {@code bytes} field value from the stream. */
503 public ByteString readBytes() throws IOException {
504 final int size = readRawVarint32();
505 if (size <= (bufferSize - bufferPos) && size > 0) {
506 // Fast path: We already have the bytes in a contiguous buffer, so
507 // just copy directly from it.
508 final ByteString result = bufferIsImmutable && enableAliasing
509 ? new BoundedByteString(buffer, bufferPos, size)
510 : ByteString.copyFrom(buffer, bufferPos, size);
513 } else if (size == 0) {
514 return ByteString.EMPTY;
516 // Slow path: Build a byte array first then copy it.
517 return new LiteralByteString(readRawBytesSlowPath(size));
521 /** Read a {@code bytes} field value from the stream. */
522 public byte[] readByteArray() throws IOException {
523 final int size = readRawVarint32();
524 if (size <= (bufferSize - bufferPos) && size > 0) {
525 // Fast path: We already have the bytes in a contiguous buffer, so
526 // just copy directly from it.
527 final byte[] result =
528 Arrays.copyOfRange(buffer, bufferPos, bufferPos + size);
532 // Slow path: Build a byte array first then copy it.
533 return readRawBytesSlowPath(size);
537 /** Read a {@code bytes} field value from the stream. */
538 public ByteBuffer readByteBuffer() throws IOException {
539 final int size = readRawVarint32();
540 if (size <= (bufferSize - bufferPos) && size > 0) {
541 // Fast path: We already have the bytes in a contiguous buffer.
542 // When aliasing is enabled, we can return a ByteBuffer pointing directly
543 // into the underlying byte array without copy if the CodedInputStream is
544 // constructed from a byte array. If aliasing is disabled or the input is
545 // from an InputStream or ByteString, we have to make a copy of the bytes.
546 ByteBuffer result = input == null && !bufferIsImmutable && enableAliasing
547 ? ByteBuffer.wrap(buffer, bufferPos, size).slice()
548 : ByteBuffer.wrap(Arrays.copyOfRange(
549 buffer, bufferPos, bufferPos + size));
552 } else if (size == 0) {
553 return Internal.EMPTY_BYTE_BUFFER;
555 // Slow path: Build a byte array first then copy it.
556 return ByteBuffer.wrap(readRawBytesSlowPath(size));
560 /** Read a {@code uint32} field value from the stream. */
561 public int readUInt32() throws IOException {
562 return readRawVarint32();
566 * Read an enum field value from the stream. Caller is responsible
567 * for converting the numeric value to an actual enum.
569 public int readEnum() throws IOException {
570 return readRawVarint32();
573 /** Read an {@code sfixed32} field value from the stream. */
574 public int readSFixed32() throws IOException {
575 return readRawLittleEndian32();
578 /** Read an {@code sfixed64} field value from the stream. */
579 public long readSFixed64() throws IOException {
580 return readRawLittleEndian64();
583 /** Read an {@code sint32} field value from the stream. */
584 public int readSInt32() throws IOException {
585 return decodeZigZag32(readRawVarint32());
588 /** Read an {@code sint64} field value from the stream. */
589 public long readSInt64() throws IOException {
590 return decodeZigZag64(readRawVarint64());
593 // =================================================================
596 * Read a raw Varint from the stream. If larger than 32 bits, discard the
599 public int readRawVarint32() throws IOException {
600 // See implementation notes for readRawVarint64
604 if (bufferSize == pos) {
608 final byte[] buffer = this.buffer;
610 if ((x = buffer[pos++]) >= 0) {
613 } else if (bufferSize - pos < 9) {
615 } else if ((x ^= (buffer[pos++] << 7)) < 0L) {
617 } else if ((x ^= (buffer[pos++] << 14)) >= 0L) {
618 x ^= (~0L << 7) ^ (~0L << 14);
619 } else if ((x ^= (buffer[pos++] << 21)) < 0L) {
620 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21);
622 int y = buffer[pos++];
624 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
631 break fastpath; // Will throw malformedVarint()
637 return (int) readRawVarint64SlowPath();
640 private void skipRawVarint() throws IOException {
641 if (bufferSize - bufferPos >= 10) {
642 final byte[] buffer = this.buffer;
644 for (int i = 0; i < 10; i++) {
645 if (buffer[pos++] >= 0) {
651 skipRawVarintSlowPath();
654 private void skipRawVarintSlowPath() throws IOException {
655 for (int i = 0; i < 10; i++) {
656 if (readRawByte() >= 0) {
660 throw InvalidProtocolBufferException.malformedVarint();
664 * Reads a varint from the input one byte at a time, so that it does not
665 * read any bytes after the end of the varint. If you simply wrapped the
666 * stream in a CodedInputStream and used {@link #readRawVarint32(InputStream)}
667 * then you would probably end up reading past the end of the varint since
668 * CodedInputStream buffers its input.
670 static int readRawVarint32(final InputStream input) throws IOException {
671 final int firstByte = input.read();
672 if (firstByte == -1) {
673 throw InvalidProtocolBufferException.truncatedMessage();
675 return readRawVarint32(firstByte, input);
679 * Like {@link #readRawVarint32(InputStream)}, but expects that the caller
680 * has already read one byte. This allows the caller to determine if EOF
681 * has been reached before attempting to read.
683 public static int readRawVarint32(
684 final int firstByte, final InputStream input) throws IOException {
685 if ((firstByte & 0x80) == 0) {
689 int result = firstByte & 0x7f;
691 for (; offset < 32; offset += 7) {
692 final int b = input.read();
694 throw InvalidProtocolBufferException.truncatedMessage();
696 result |= (b & 0x7f) << offset;
697 if ((b & 0x80) == 0) {
701 // Keep reading up to 64 bits.
702 for (; offset < 64; offset += 7) {
703 final int b = input.read();
705 throw InvalidProtocolBufferException.truncatedMessage();
707 if ((b & 0x80) == 0) {
711 throw InvalidProtocolBufferException.malformedVarint();
714 /** Read a raw Varint from the stream. */
715 public long readRawVarint64() throws IOException {
716 // Implementation notes:
718 // Optimized for one-byte values, expected to be common.
719 // The particular code below was selected from various candidates
720 // empirically, by winning VarintBenchmark.
722 // Sign extension of (signed) Java bytes is usually a nuisance, but
723 // we exploit it here to more easily obtain the sign of bytes read.
724 // Instead of cleaning up the sign extension bits by masking eagerly,
725 // we delay until we find the final (positive) byte, when we clear all
726 // accumulated bits with one xor. We depend on javac to constant fold.
730 if (bufferSize == pos) {
734 final byte[] buffer = this.buffer;
737 if ((y = buffer[pos++]) >= 0) {
740 } else if (bufferSize - pos < 9) {
742 } else if ((x = y ^ (buffer[pos++] << 7)) < 0L) {
744 } else if ((x ^= (buffer[pos++] << 14)) >= 0L) {
745 x ^= (~0L << 7) ^ (~0L << 14);
746 } else if ((x ^= (buffer[pos++] << 21)) < 0L) {
747 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21);
748 } else if ((x ^= ((long) buffer[pos++] << 28)) >= 0L) {
749 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
750 } else if ((x ^= ((long) buffer[pos++] << 35)) < 0L) {
751 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
752 } else if ((x ^= ((long) buffer[pos++] << 42)) >= 0L) {
753 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
754 } else if ((x ^= ((long) buffer[pos++] << 49)) < 0L) {
755 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42)
758 x ^= ((long) buffer[pos++] << 56);
759 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42)
760 ^ (~0L << 49) ^ (~0L << 56);
762 if (buffer[pos++] < 0L) {
763 break fastpath; // Will throw malformedVarint()
770 return readRawVarint64SlowPath();
773 /** Variant of readRawVarint64 for when uncomfortably close to the limit. */
774 /* Visible for testing */
775 long readRawVarint64SlowPath() throws IOException {
777 for (int shift = 0; shift < 64; shift += 7) {
778 final byte b = readRawByte();
779 result |= (long) (b & 0x7F) << shift;
780 if ((b & 0x80) == 0) {
784 throw InvalidProtocolBufferException.malformedVarint();
787 /** Read a 32-bit little-endian integer from the stream. */
788 public int readRawLittleEndian32() throws IOException {
791 // hand-inlined ensureAvailable(4);
792 if (bufferSize - pos < 4) {
797 final byte[] buffer = this.buffer;
799 return (((buffer[pos] & 0xff)) |
800 ((buffer[pos + 1] & 0xff) << 8) |
801 ((buffer[pos + 2] & 0xff) << 16) |
802 ((buffer[pos + 3] & 0xff) << 24));
805 /** Read a 64-bit little-endian integer from the stream. */
806 public long readRawLittleEndian64() throws IOException {
809 // hand-inlined ensureAvailable(8);
810 if (bufferSize - pos < 8) {
815 final byte[] buffer = this.buffer;
817 return ((((long) buffer[pos] & 0xffL)) |
818 (((long) buffer[pos + 1] & 0xffL) << 8) |
819 (((long) buffer[pos + 2] & 0xffL) << 16) |
820 (((long) buffer[pos + 3] & 0xffL) << 24) |
821 (((long) buffer[pos + 4] & 0xffL) << 32) |
822 (((long) buffer[pos + 5] & 0xffL) << 40) |
823 (((long) buffer[pos + 6] & 0xffL) << 48) |
824 (((long) buffer[pos + 7] & 0xffL) << 56));
828 * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers
829 * into values that can be efficiently encoded with varint. (Otherwise,
830 * negative values must be sign-extended to 64 bits to be varint encoded,
831 * thus always taking 10 bytes on the wire.)
833 * @param n An unsigned 32-bit integer, stored in a signed int because
834 * Java has no explicit unsigned support.
835 * @return A signed 32-bit integer.
837 public static int decodeZigZag32(final int n) {
838 return (n >>> 1) ^ -(n & 1);
842 * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers
843 * into values that can be efficiently encoded with varint. (Otherwise,
844 * negative values must be sign-extended to 64 bits to be varint encoded,
845 * thus always taking 10 bytes on the wire.)
847 * @param n An unsigned 64-bit integer, stored in a signed int because
848 * Java has no explicit unsigned support.
849 * @return A signed 64-bit integer.
851 public static long decodeZigZag64(final long n) {
852 return (n >>> 1) ^ -(n & 1);
855 // -----------------------------------------------------------------
857 private final byte[] buffer;
858 private final boolean bufferIsImmutable;
859 private int bufferSize;
860 private int bufferSizeAfterLimit;
861 private int bufferPos;
862 private final InputStream input;
864 private boolean enableAliasing = false;
867 * The total number of bytes read before the current buffer. The total
868 * bytes read up to the current position can be computed as
869 * {@code totalBytesRetired + bufferPos}. This value may be negative if
870 * reading started in the middle of the current buffer (e.g. if the
871 * constructor that takes a byte array and an offset was used).
873 private int totalBytesRetired;
875 /** The absolute position of the end of the current message. */
876 private int currentLimit = Integer.MAX_VALUE;
878 /** See setRecursionLimit() */
879 private int recursionDepth;
880 private int recursionLimit = DEFAULT_RECURSION_LIMIT;
882 /** See setSizeLimit() */
883 private int sizeLimit = DEFAULT_SIZE_LIMIT;
885 private static final int DEFAULT_RECURSION_LIMIT = 64;
886 private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB
887 private static final int BUFFER_SIZE = 4096;
889 private CodedInputStream(final byte[] buffer, final int off, final int len) {
890 this.buffer = buffer;
891 bufferSize = off + len;
893 totalBytesRetired = -off;
895 bufferIsImmutable = false;
898 private CodedInputStream(final InputStream input) {
899 buffer = new byte[BUFFER_SIZE];
902 totalBytesRetired = 0;
904 bufferIsImmutable = false;
907 private CodedInputStream(final LiteralByteString byteString) {
908 buffer = byteString.bytes;
909 bufferPos = byteString.getOffsetIntoBytes();
910 bufferSize = bufferPos + byteString.size();
911 totalBytesRetired = -bufferPos;
913 bufferIsImmutable = true;
916 public void enableAliasing(boolean enabled) {
917 this.enableAliasing = enabled;
921 * Set the maximum message recursion depth. In order to prevent malicious
922 * messages from causing stack overflows, {@code CodedInputStream} limits
923 * how deeply messages may be nested. The default limit is 64.
925 * @return the old limit.
927 public int setRecursionLimit(final int limit) {
929 throw new IllegalArgumentException(
930 "Recursion limit cannot be negative: " + limit);
932 final int oldLimit = recursionLimit;
933 recursionLimit = limit;
938 * Set the maximum message size. In order to prevent malicious
939 * messages from exhausting memory or causing integer overflows,
940 * {@code CodedInputStream} limits how large a message may be.
941 * The default limit is 64MB. You should set this limit as small
942 * as you can without harming your app's functionality. Note that
943 * size limits only apply when reading from an {@code InputStream}, not
944 * when constructed around a raw byte array (nor with
945 * {@link ByteString#newCodedInput}).
947 * If you want to read several messages from a single CodedInputStream, you
948 * could call {@link #resetSizeCounter()} after each one to avoid hitting the
951 * @return the old limit.
953 public int setSizeLimit(final int limit) {
955 throw new IllegalArgumentException(
956 "Size limit cannot be negative: " + limit);
958 final int oldLimit = sizeLimit;
964 * Resets the current size counter to zero (see {@link #setSizeLimit(int)}).
966 public void resetSizeCounter() {
967 totalBytesRetired = -bufferPos;
971 * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This
972 * is called when descending into a length-delimited embedded message.
974 * <p>Note that {@code pushLimit()} does NOT affect how many bytes the
975 * {@code CodedInputStream} reads from an underlying {@code InputStream} when
976 * refreshing its buffer. If you need to prevent reading past a certain
977 * point in the underlying {@code InputStream} (e.g. because you expect it to
978 * contain more data after the end of the message which you need to handle
979 * differently) then you must place a wrapper around your {@code InputStream}
980 * which limits the amount of data that can be read from it.
982 * @return the old limit.
984 public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
986 throw InvalidProtocolBufferException.negativeSize();
988 byteLimit += totalBytesRetired + bufferPos;
989 final int oldLimit = currentLimit;
990 if (byteLimit > oldLimit) {
991 throw InvalidProtocolBufferException.truncatedMessage();
993 currentLimit = byteLimit;
995 recomputeBufferSizeAfterLimit();
1000 private void recomputeBufferSizeAfterLimit() {
1001 bufferSize += bufferSizeAfterLimit;
1002 final int bufferEnd = totalBytesRetired + bufferSize;
1003 if (bufferEnd > currentLimit) {
1004 // Limit is in current buffer.
1005 bufferSizeAfterLimit = bufferEnd - currentLimit;
1006 bufferSize -= bufferSizeAfterLimit;
1008 bufferSizeAfterLimit = 0;
1013 * Discards the current limit, returning to the previous limit.
1015 * @param oldLimit The old limit, as returned by {@code pushLimit}.
1017 public void popLimit(final int oldLimit) {
1018 currentLimit = oldLimit;
1019 recomputeBufferSizeAfterLimit();
1023 * Returns the number of bytes to be read before the current limit.
1024 * If no limit is set, returns -1.
1026 public int getBytesUntilLimit() {
1027 if (currentLimit == Integer.MAX_VALUE) {
1031 final int currentAbsolutePosition = totalBytesRetired + bufferPos;
1032 return currentLimit - currentAbsolutePosition;
1036 * Returns true if the stream has reached the end of the input. This is the
1037 * case if either the end of the underlying input source has been reached or
1038 * if the stream has reached a limit created using {@link #pushLimit(int)}.
1040 public boolean isAtEnd() throws IOException {
1041 return bufferPos == bufferSize && !tryRefillBuffer(1);
1045 * The total bytes read up to the current position. Calling
1046 * {@link #resetSizeCounter()} resets this value to zero.
1048 public int getTotalBytesRead() {
1049 return totalBytesRetired + bufferPos;
1052 private interface RefillCallback {
1056 private RefillCallback refillCallback = null;
1059 * Ensures that at least {@code n} bytes are available in the buffer, reading
1060 * more bytes from the input if necessary to make it so. Caller must ensure
1061 * that the requested space is less than BUFFER_SIZE.
1063 * @throws InvalidProtocolBufferException The end of the stream or the current
1064 * limit was reached.
1066 private void ensureAvailable(int n) throws IOException {
1067 if (bufferSize - bufferPos < n) {
1073 * Reads more bytes from the input, making at least {@code n} bytes available
1074 * in the buffer. Caller must ensure that the requested space is not yet
1075 * available, and that the requested space is less than BUFFER_SIZE.
1077 * @throws InvalidProtocolBufferException The end of the stream or the current
1078 * limit was reached.
1080 private void refillBuffer(int n) throws IOException {
1081 if (!tryRefillBuffer(n)) {
1082 throw InvalidProtocolBufferException.truncatedMessage();
1087 * Tries to read more bytes from the input, making at least {@code n} bytes
1088 * available in the buffer. Caller must ensure that the requested space is
1089 * not yet available, and that the requested space is less than BUFFER_SIZE.
1091 * @return {@code true} if the bytes could be made available; {@code false}
1092 * if the end of the stream or the current limit was reached.
1094 private boolean tryRefillBuffer(int n) throws IOException {
1095 if (bufferPos + n <= bufferSize) {
1096 throw new IllegalStateException(
1097 "refillBuffer() called when " + n +
1098 " bytes were already available in buffer");
1101 if (totalBytesRetired + bufferPos + n > currentLimit) {
1102 // Oops, we hit a limit.
1106 if (refillCallback != null) {
1107 refillCallback.onRefill();
1110 if (input != null) {
1111 int pos = bufferPos;
1113 if (bufferSize > pos) {
1114 System.arraycopy(buffer, pos, buffer, 0, bufferSize - pos);
1116 totalBytesRetired += pos;
1121 int bytesRead = input.read(buffer, bufferSize, buffer.length - bufferSize);
1122 if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) {
1123 throw new IllegalStateException(
1124 "InputStream#read(byte[]) returned invalid result: " + bytesRead +
1125 "\nThe InputStream implementation is buggy.");
1127 if (bytesRead > 0) {
1128 bufferSize += bytesRead;
1129 // Integer-overflow-conscious check against sizeLimit
1130 if (totalBytesRetired + n - sizeLimit > 0) {
1131 throw InvalidProtocolBufferException.sizeLimitExceeded();
1133 recomputeBufferSizeAfterLimit();
1134 return (bufferSize >= n) ? true : tryRefillBuffer(n);
1142 * Read one byte from the input.
1144 * @throws InvalidProtocolBufferException The end of the stream or the current
1145 * limit was reached.
1147 public byte readRawByte() throws IOException {
1148 if (bufferPos == bufferSize) {
1151 return buffer[bufferPos++];
1155 * Read a fixed size of bytes from the input.
1157 * @throws InvalidProtocolBufferException The end of the stream or the current
1158 * limit was reached.
1160 public byte[] readRawBytes(final int size) throws IOException {
1161 final int pos = bufferPos;
1162 if (size <= (bufferSize - pos) && size > 0) {
1163 bufferPos = pos + size;
1164 return Arrays.copyOfRange(buffer, pos, pos + size);
1166 return readRawBytesSlowPath(size);
1171 * Exactly like readRawBytes, but caller must have already checked the fast
1172 * path: (size <= (bufferSize - pos) && size > 0)
1174 private byte[] readRawBytesSlowPath(final int size) throws IOException {
1177 return Internal.EMPTY_BYTE_ARRAY;
1179 throw InvalidProtocolBufferException.negativeSize();
1183 if (totalBytesRetired + bufferPos + size > currentLimit) {
1184 // Read to the end of the stream anyway.
1185 skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
1187 throw InvalidProtocolBufferException.truncatedMessage();
1190 if (size < BUFFER_SIZE) {
1191 // Reading more bytes than are in the buffer, but not an excessive number
1192 // of bytes. We can safely allocate the resulting array ahead of time.
1194 // First copy what we have.
1195 final byte[] bytes = new byte[size];
1196 int pos = bufferSize - bufferPos;
1197 System.arraycopy(buffer, bufferPos, bytes, 0, pos);
1198 bufferPos = bufferSize;
1200 // We want to refill the buffer and then copy from the buffer into our
1201 // byte array rather than reading directly into our byte array because
1202 // the input may be unbuffered.
1203 ensureAvailable(size - pos);
1204 System.arraycopy(buffer, 0, bytes, pos, size - pos);
1205 bufferPos = size - pos;
1209 // The size is very large. For security reasons, we can't allocate the
1210 // entire byte array yet. The size comes directly from the input, so a
1211 // maliciously-crafted message could provide a bogus very large size in
1212 // order to trick the app into allocating a lot of memory. We avoid this
1213 // by allocating and reading only a small chunk at a time, so that the
1214 // malicious message must actually *be* extremely large to cause
1215 // problems. Meanwhile, we limit the allowed size of a message elsewhere.
1217 // Remember the buffer markers since we'll have to copy the bytes out of
1219 final int originalBufferPos = bufferPos;
1220 final int originalBufferSize = bufferSize;
1222 // Mark the current buffer consumed.
1223 totalBytesRetired += bufferSize;
1227 // Read all the rest of the bytes we need.
1228 int sizeLeft = size - (originalBufferSize - originalBufferPos);
1229 final List<byte[]> chunks = new ArrayList<byte[]>();
1231 while (sizeLeft > 0) {
1232 final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
1234 while (pos < chunk.length) {
1235 final int n = (input == null) ? -1 :
1236 input.read(chunk, pos, chunk.length - pos);
1238 throw InvalidProtocolBufferException.truncatedMessage();
1240 totalBytesRetired += n;
1243 sizeLeft -= chunk.length;
1247 // OK, got everything. Now concatenate it all into one buffer.
1248 final byte[] bytes = new byte[size];
1250 // Start by copying the leftover bytes from this.buffer.
1251 int pos = originalBufferSize - originalBufferPos;
1252 System.arraycopy(buffer, originalBufferPos, bytes, 0, pos);
1254 // And now all the chunks.
1255 for (final byte[] chunk : chunks) {
1256 System.arraycopy(chunk, 0, bytes, pos, chunk.length);
1257 pos += chunk.length;
1266 * Reads and discards {@code size} bytes.
1268 * @throws InvalidProtocolBufferException The end of the stream or the current
1269 * limit was reached.
1271 public void skipRawBytes(final int size) throws IOException {
1272 if (size <= (bufferSize - bufferPos) && size >= 0) {
1273 // We have all the bytes we need already.
1276 skipRawBytesSlowPath(size);
1281 * Exactly like skipRawBytes, but caller must have already checked the fast
1282 * path: (size <= (bufferSize - pos) && size >= 0)
1284 private void skipRawBytesSlowPath(final int size) throws IOException {
1286 throw InvalidProtocolBufferException.negativeSize();
1289 if (totalBytesRetired + bufferPos + size > currentLimit) {
1290 // Read to the end of the stream anyway.
1291 skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
1293 throw InvalidProtocolBufferException.truncatedMessage();
1296 // Skipping more bytes than are in the buffer. First skip what we have.
1297 int pos = bufferSize - bufferPos;
1298 bufferPos = bufferSize;
1300 // Keep refilling the buffer until we get to the point we wanted to skip to.
1301 // This has the side effect of ensuring the limits are updated correctly.
1303 while (size - pos > bufferSize) {
1305 bufferPos = bufferSize;
1309 bufferPos = size - pos;