- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / protobuf / java / src / main / java / com / google / protobuf / CodedInputStream.java
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // http://code.google.com/p/protobuf/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 package com.google.protobuf;
32
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.util.ArrayList;
36 import java.util.List;
37
38 /**
39  * Reads and decodes protocol message fields.
40  *
41  * This class contains two kinds of methods:  methods that read specific
42  * protocol message constructs and field types (e.g. {@link #readTag()} and
43  * {@link #readInt32()}) and methods that read low-level values (e.g.
44  * {@link #readRawVarint32()} and {@link #readRawBytes}).  If you are reading
45  * encoded protocol messages, you should use the former methods, but if you are
46  * reading some other format of your own design, use the latter.
47  *
48  * @author kenton@google.com Kenton Varda
49  */
50 public final class CodedInputStream {
51   /**
52    * Create a new CodedInputStream wrapping the given InputStream.
53    */
54   public static CodedInputStream newInstance(final InputStream input) {
55     return new CodedInputStream(input);
56   }
57
58   /**
59    * Create a new CodedInputStream wrapping the given byte array.
60    */
61   public static CodedInputStream newInstance(final byte[] buf) {
62     return newInstance(buf, 0, buf.length);
63   }
64
65   /**
66    * Create a new CodedInputStream wrapping the given byte array slice.
67    */
68   public static CodedInputStream newInstance(final byte[] buf, final int off,
69                                              final int len) {
70     CodedInputStream result = new CodedInputStream(buf, off, len);
71     try {
72       // Some uses of CodedInputStream can be more efficient if they know
73       // exactly how many bytes are available.  By pushing the end point of the
74       // buffer as a limit, we allow them to get this information via
75       // getBytesUntilLimit().  Pushing a limit that we know is at the end of
76       // the stream can never hurt, since we can never past that point anyway.
77       result.pushLimit(len);
78     } catch (InvalidProtocolBufferException ex) {
79       // The only reason pushLimit() might throw an exception here is if len
80       // is negative. Normally pushLimit()'s parameter comes directly off the
81       // wire, so it's important to catch exceptions in case of corrupt or
82       // malicious data. However, in this case, we expect that len is not a
83       // user-supplied value, so we can assume that it being negative indicates
84       // a programming error. Therefore, throwing an unchecked exception is
85       // appropriate.
86       throw new IllegalArgumentException(ex);
87     }
88     return result;
89   }
90
91   // -----------------------------------------------------------------
92
93   /**
94    * Attempt to read a field tag, returning zero if we have reached EOF.
95    * Protocol message parsers use this to read tags, since a protocol message
96    * may legally end wherever a tag occurs, and zero is not a valid tag number.
97    */
98   public int readTag() throws IOException {
99     if (isAtEnd()) {
100       lastTag = 0;
101       return 0;
102     }
103
104     lastTag = readRawVarint32();
105     if (WireFormat.getTagFieldNumber(lastTag) == 0) {
106       // If we actually read zero (or any tag number corresponding to field
107       // number zero), that's not a valid tag.
108       throw InvalidProtocolBufferException.invalidTag();
109     }
110     return lastTag;
111   }
112
113   /**
114    * Verifies that the last call to readTag() returned the given tag value.
115    * This is used to verify that a nested group ended with the correct
116    * end tag.
117    *
118    * @throws InvalidProtocolBufferException {@code value} does not match the
119    *                                        last tag.
120    */
121   public void checkLastTagWas(final int value)
122                               throws InvalidProtocolBufferException {
123     if (lastTag != value) {
124       throw InvalidProtocolBufferException.invalidEndTag();
125     }
126   }
127
128   /**
129    * Reads and discards a single field, given its tag value.
130    *
131    * @return {@code false} if the tag is an endgroup tag, in which case
132    *         nothing is skipped.  Otherwise, returns {@code true}.
133    */
134   public boolean skipField(final int tag) throws IOException {
135     switch (WireFormat.getTagWireType(tag)) {
136       case WireFormat.WIRETYPE_VARINT:
137         readInt32();
138         return true;
139       case WireFormat.WIRETYPE_FIXED64:
140         readRawLittleEndian64();
141         return true;
142       case WireFormat.WIRETYPE_LENGTH_DELIMITED:
143         skipRawBytes(readRawVarint32());
144         return true;
145       case WireFormat.WIRETYPE_START_GROUP:
146         skipMessage();
147         checkLastTagWas(
148           WireFormat.makeTag(WireFormat.getTagFieldNumber(tag),
149                              WireFormat.WIRETYPE_END_GROUP));
150         return true;
151       case WireFormat.WIRETYPE_END_GROUP:
152         return false;
153       case WireFormat.WIRETYPE_FIXED32:
154         readRawLittleEndian32();
155         return true;
156       default:
157         throw InvalidProtocolBufferException.invalidWireType();
158     }
159   }
160
161   /**
162    * Reads and discards an entire message.  This will read either until EOF
163    * or until an endgroup tag, whichever comes first.
164    */
165   public void skipMessage() throws IOException {
166     while (true) {
167       final int tag = readTag();
168       if (tag == 0 || !skipField(tag)) {
169         return;
170       }
171     }
172   }
173
174   // -----------------------------------------------------------------
175
176   /** Read a {@code double} field value from the stream. */
177   public double readDouble() throws IOException {
178     return Double.longBitsToDouble(readRawLittleEndian64());
179   }
180
181   /** Read a {@code float} field value from the stream. */
182   public float readFloat() throws IOException {
183     return Float.intBitsToFloat(readRawLittleEndian32());
184   }
185
186   /** Read a {@code uint64} field value from the stream. */
187   public long readUInt64() throws IOException {
188     return readRawVarint64();
189   }
190
191   /** Read an {@code int64} field value from the stream. */
192   public long readInt64() throws IOException {
193     return readRawVarint64();
194   }
195
196   /** Read an {@code int32} field value from the stream. */
197   public int readInt32() throws IOException {
198     return readRawVarint32();
199   }
200
201   /** Read a {@code fixed64} field value from the stream. */
202   public long readFixed64() throws IOException {
203     return readRawLittleEndian64();
204   }
205
206   /** Read a {@code fixed32} field value from the stream. */
207   public int readFixed32() throws IOException {
208     return readRawLittleEndian32();
209   }
210
211   /** Read a {@code bool} field value from the stream. */
212   public boolean readBool() throws IOException {
213     return readRawVarint32() != 0;
214   }
215
216   /** Read a {@code string} field value from the stream. */
217   public String readString() throws IOException {
218     final int size = readRawVarint32();
219     if (size <= (bufferSize - bufferPos) && size > 0) {
220       // Fast path:  We already have the bytes in a contiguous buffer, so
221       //   just copy directly from it.
222       final String result = new String(buffer, bufferPos, size, "UTF-8");
223       bufferPos += size;
224       return result;
225     } else {
226       // Slow path:  Build a byte array first then copy it.
227       return new String(readRawBytes(size), "UTF-8");
228     }
229   }
230
231   /** Read a {@code group} field value from the stream. */
232   public void readGroup(final int fieldNumber,
233                         final MessageLite.Builder builder,
234                         final ExtensionRegistryLite extensionRegistry)
235       throws IOException {
236     if (recursionDepth >= recursionLimit) {
237       throw InvalidProtocolBufferException.recursionLimitExceeded();
238     }
239     ++recursionDepth;
240     builder.mergeFrom(this, extensionRegistry);
241     checkLastTagWas(
242       WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
243     --recursionDepth;
244   }
245
246   /** Read a {@code group} field value from the stream. */
247   public <T extends MessageLite> T readGroup(
248       final int fieldNumber,
249       final Parser<T> parser,
250       final ExtensionRegistryLite extensionRegistry)
251       throws IOException {
252     if (recursionDepth >= recursionLimit) {
253       throw InvalidProtocolBufferException.recursionLimitExceeded();
254     }
255     ++recursionDepth;
256     T result = parser.parsePartialFrom(this, extensionRegistry);
257     checkLastTagWas(
258       WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
259     --recursionDepth;
260     return result;
261   }
262
263   /**
264    * Reads a {@code group} field value from the stream and merges it into the
265    * given {@link UnknownFieldSet}.
266    *
267    * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so
268    *             you can just call {@link #readGroup}.
269    */
270   @Deprecated
271   public void readUnknownGroup(final int fieldNumber,
272                                final MessageLite.Builder builder)
273       throws IOException {
274     // We know that UnknownFieldSet will ignore any ExtensionRegistry so it
275     // is safe to pass null here.  (We can't call
276     // ExtensionRegistry.getEmptyRegistry() because that would make this
277     // class depend on ExtensionRegistry, which is not part of the lite
278     // library.)
279     readGroup(fieldNumber, builder, null);
280   }
281
282   /** Read an embedded message field value from the stream. */
283   public void readMessage(final MessageLite.Builder builder,
284                           final ExtensionRegistryLite extensionRegistry)
285       throws IOException {
286     final int length = readRawVarint32();
287     if (recursionDepth >= recursionLimit) {
288       throw InvalidProtocolBufferException.recursionLimitExceeded();
289     }
290     final int oldLimit = pushLimit(length);
291     ++recursionDepth;
292     builder.mergeFrom(this, extensionRegistry);
293     checkLastTagWas(0);
294     --recursionDepth;
295     popLimit(oldLimit);
296   }
297
298   /** Read an embedded message field value from the stream. */
299   public <T extends MessageLite> T readMessage(
300       final Parser<T> parser,
301       final ExtensionRegistryLite extensionRegistry)
302       throws IOException {
303     int length = readRawVarint32();
304     if (recursionDepth >= recursionLimit) {
305       throw InvalidProtocolBufferException.recursionLimitExceeded();
306     }
307     final int oldLimit = pushLimit(length);
308     ++recursionDepth;
309     T result = parser.parsePartialFrom(this, extensionRegistry);
310     checkLastTagWas(0);
311     --recursionDepth;
312     popLimit(oldLimit);
313     return result;
314   }
315
316   /** Read a {@code bytes} field value from the stream. */
317   public ByteString readBytes() throws IOException {
318     final int size = readRawVarint32();
319     if (size == 0) {
320       return ByteString.EMPTY;
321     } else if (size <= (bufferSize - bufferPos) && size > 0) {
322       // Fast path:  We already have the bytes in a contiguous buffer, so
323       //   just copy directly from it.
324       final ByteString result = ByteString.copyFrom(buffer, bufferPos, size);
325       bufferPos += size;
326       return result;
327     } else {
328       // Slow path:  Build a byte array first then copy it.
329       return ByteString.copyFrom(readRawBytes(size));
330     }
331   }
332
333   /** Read a {@code uint32} field value from the stream. */
334   public int readUInt32() throws IOException {
335     return readRawVarint32();
336   }
337
338   /**
339    * Read an enum field value from the stream.  Caller is responsible
340    * for converting the numeric value to an actual enum.
341    */
342   public int readEnum() throws IOException {
343     return readRawVarint32();
344   }
345
346   /** Read an {@code sfixed32} field value from the stream. */
347   public int readSFixed32() throws IOException {
348     return readRawLittleEndian32();
349   }
350
351   /** Read an {@code sfixed64} field value from the stream. */
352   public long readSFixed64() throws IOException {
353     return readRawLittleEndian64();
354   }
355
356   /** Read an {@code sint32} field value from the stream. */
357   public int readSInt32() throws IOException {
358     return decodeZigZag32(readRawVarint32());
359   }
360
361   /** Read an {@code sint64} field value from the stream. */
362   public long readSInt64() throws IOException {
363     return decodeZigZag64(readRawVarint64());
364   }
365
366   // =================================================================
367
368   /**
369    * Read a raw Varint from the stream.  If larger than 32 bits, discard the
370    * upper bits.
371    */
372   public int readRawVarint32() throws IOException {
373     byte tmp = readRawByte();
374     if (tmp >= 0) {
375       return tmp;
376     }
377     int result = tmp & 0x7f;
378     if ((tmp = readRawByte()) >= 0) {
379       result |= tmp << 7;
380     } else {
381       result |= (tmp & 0x7f) << 7;
382       if ((tmp = readRawByte()) >= 0) {
383         result |= tmp << 14;
384       } else {
385         result |= (tmp & 0x7f) << 14;
386         if ((tmp = readRawByte()) >= 0) {
387           result |= tmp << 21;
388         } else {
389           result |= (tmp & 0x7f) << 21;
390           result |= (tmp = readRawByte()) << 28;
391           if (tmp < 0) {
392             // Discard upper 32 bits.
393             for (int i = 0; i < 5; i++) {
394               if (readRawByte() >= 0) {
395                 return result;
396               }
397             }
398             throw InvalidProtocolBufferException.malformedVarint();
399           }
400         }
401       }
402     }
403     return result;
404   }
405
406   /**
407    * Reads a varint from the input one byte at a time, so that it does not
408    * read any bytes after the end of the varint.  If you simply wrapped the
409    * stream in a CodedInputStream and used {@link #readRawVarint32(InputStream)}
410    * then you would probably end up reading past the end of the varint since
411    * CodedInputStream buffers its input.
412    */
413   static int readRawVarint32(final InputStream input) throws IOException {
414     final int firstByte = input.read();
415     if (firstByte == -1) {
416       throw InvalidProtocolBufferException.truncatedMessage();
417     }
418     return readRawVarint32(firstByte, input);
419   }
420
421   /**
422    * Like {@link #readRawVarint32(InputStream)}, but expects that the caller
423    * has already read one byte.  This allows the caller to determine if EOF
424    * has been reached before attempting to read.
425    */
426   public static int readRawVarint32(
427       final int firstByte, final InputStream input) throws IOException {
428     if ((firstByte & 0x80) == 0) {
429       return firstByte;
430     }
431
432     int result = firstByte & 0x7f;
433     int offset = 7;
434     for (; offset < 32; offset += 7) {
435       final int b = input.read();
436       if (b == -1) {
437         throw InvalidProtocolBufferException.truncatedMessage();
438       }
439       result |= (b & 0x7f) << offset;
440       if ((b & 0x80) == 0) {
441         return result;
442       }
443     }
444     // Keep reading up to 64 bits.
445     for (; offset < 64; offset += 7) {
446       final int b = input.read();
447       if (b == -1) {
448         throw InvalidProtocolBufferException.truncatedMessage();
449       }
450       if ((b & 0x80) == 0) {
451         return result;
452       }
453     }
454     throw InvalidProtocolBufferException.malformedVarint();
455   }
456
457   /** Read a raw Varint from the stream. */
458   public long readRawVarint64() throws IOException {
459     int shift = 0;
460     long result = 0;
461     while (shift < 64) {
462       final byte b = readRawByte();
463       result |= (long)(b & 0x7F) << shift;
464       if ((b & 0x80) == 0) {
465         return result;
466       }
467       shift += 7;
468     }
469     throw InvalidProtocolBufferException.malformedVarint();
470   }
471
472   /** Read a 32-bit little-endian integer from the stream. */
473   public int readRawLittleEndian32() throws IOException {
474     final byte b1 = readRawByte();
475     final byte b2 = readRawByte();
476     final byte b3 = readRawByte();
477     final byte b4 = readRawByte();
478     return (((int)b1 & 0xff)      ) |
479            (((int)b2 & 0xff) <<  8) |
480            (((int)b3 & 0xff) << 16) |
481            (((int)b4 & 0xff) << 24);
482   }
483
484   /** Read a 64-bit little-endian integer from the stream. */
485   public long readRawLittleEndian64() throws IOException {
486     final byte b1 = readRawByte();
487     final byte b2 = readRawByte();
488     final byte b3 = readRawByte();
489     final byte b4 = readRawByte();
490     final byte b5 = readRawByte();
491     final byte b6 = readRawByte();
492     final byte b7 = readRawByte();
493     final byte b8 = readRawByte();
494     return (((long)b1 & 0xff)      ) |
495            (((long)b2 & 0xff) <<  8) |
496            (((long)b3 & 0xff) << 16) |
497            (((long)b4 & 0xff) << 24) |
498            (((long)b5 & 0xff) << 32) |
499            (((long)b6 & 0xff) << 40) |
500            (((long)b7 & 0xff) << 48) |
501            (((long)b8 & 0xff) << 56);
502   }
503
504   /**
505    * Decode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
506    * into values that can be efficiently encoded with varint.  (Otherwise,
507    * negative values must be sign-extended to 64 bits to be varint encoded,
508    * thus always taking 10 bytes on the wire.)
509    *
510    * @param n An unsigned 32-bit integer, stored in a signed int because
511    *          Java has no explicit unsigned support.
512    * @return A signed 32-bit integer.
513    */
514   public static int decodeZigZag32(final int n) {
515     return (n >>> 1) ^ -(n & 1);
516   }
517
518   /**
519    * Decode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
520    * into values that can be efficiently encoded with varint.  (Otherwise,
521    * negative values must be sign-extended to 64 bits to be varint encoded,
522    * thus always taking 10 bytes on the wire.)
523    *
524    * @param n An unsigned 64-bit integer, stored in a signed int because
525    *          Java has no explicit unsigned support.
526    * @return A signed 64-bit integer.
527    */
528   public static long decodeZigZag64(final long n) {
529     return (n >>> 1) ^ -(n & 1);
530   }
531
532   // -----------------------------------------------------------------
533
534   private final byte[] buffer;
535   private int bufferSize;
536   private int bufferSizeAfterLimit;
537   private int bufferPos;
538   private final InputStream input;
539   private int lastTag;
540
541   /**
542    * The total number of bytes read before the current buffer.  The total
543    * bytes read up to the current position can be computed as
544    * {@code totalBytesRetired + bufferPos}.  This value may be negative if
545    * reading started in the middle of the current buffer (e.g. if the
546    * constructor that takes a byte array and an offset was used).
547    */
548   private int totalBytesRetired;
549
550   /** The absolute position of the end of the current message. */
551   private int currentLimit = Integer.MAX_VALUE;
552
553   /** See setRecursionLimit() */
554   private int recursionDepth;
555   private int recursionLimit = DEFAULT_RECURSION_LIMIT;
556
557   /** See setSizeLimit() */
558   private int sizeLimit = DEFAULT_SIZE_LIMIT;
559
560   private static final int DEFAULT_RECURSION_LIMIT = 64;
561   private static final int DEFAULT_SIZE_LIMIT = 64 << 20;  // 64MB
562   private static final int BUFFER_SIZE = 4096;
563
564   private CodedInputStream(final byte[] buffer, final int off, final int len) {
565     this.buffer = buffer;
566     bufferSize = off + len;
567     bufferPos = off;
568     totalBytesRetired = -off;
569     input = null;
570   }
571
572   private CodedInputStream(final InputStream input) {
573     buffer = new byte[BUFFER_SIZE];
574     bufferSize = 0;
575     bufferPos = 0;
576     totalBytesRetired = 0;
577     this.input = input;
578   }
579
580   /**
581    * Set the maximum message recursion depth.  In order to prevent malicious
582    * messages from causing stack overflows, {@code CodedInputStream} limits
583    * how deeply messages may be nested.  The default limit is 64.
584    *
585    * @return the old limit.
586    */
587   public int setRecursionLimit(final int limit) {
588     if (limit < 0) {
589       throw new IllegalArgumentException(
590         "Recursion limit cannot be negative: " + limit);
591     }
592     final int oldLimit = recursionLimit;
593     recursionLimit = limit;
594     return oldLimit;
595   }
596
597   /**
598    * Set the maximum message size.  In order to prevent malicious
599    * messages from exhausting memory or causing integer overflows,
600    * {@code CodedInputStream} limits how large a message may be.
601    * The default limit is 64MB.  You should set this limit as small
602    * as you can without harming your app's functionality.  Note that
603    * size limits only apply when reading from an {@code InputStream}, not
604    * when constructed around a raw byte array (nor with
605    * {@link ByteString#newCodedInput}).
606    * <p>
607    * If you want to read several messages from a single CodedInputStream, you
608    * could call {@link #resetSizeCounter()} after each one to avoid hitting the
609    * size limit.
610    *
611    * @return the old limit.
612    */
613   public int setSizeLimit(final int limit) {
614     if (limit < 0) {
615       throw new IllegalArgumentException(
616         "Size limit cannot be negative: " + limit);
617     }
618     final int oldLimit = sizeLimit;
619     sizeLimit = limit;
620     return oldLimit;
621   }
622
623   /**
624    * Resets the current size counter to zero (see {@link #setSizeLimit(int)}).
625    */
626   public void resetSizeCounter() {
627     totalBytesRetired = -bufferPos;
628   }
629
630   /**
631    * Sets {@code currentLimit} to (current position) + {@code byteLimit}.  This
632    * is called when descending into a length-delimited embedded message.
633    *
634    * <p>Note that {@code pushLimit()} does NOT affect how many bytes the
635    * {@code CodedInputStream} reads from an underlying {@code InputStream} when
636    * refreshing its buffer.  If you need to prevent reading past a certain
637    * point in the underlying {@code InputStream} (e.g. because you expect it to
638    * contain more data after the end of the message which you need to handle
639    * differently) then you must place a wrapper around your {@code InputStream}
640    * which limits the amount of data that can be read from it.
641    *
642    * @return the old limit.
643    */
644   public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
645     if (byteLimit < 0) {
646       throw InvalidProtocolBufferException.negativeSize();
647     }
648     byteLimit += totalBytesRetired + bufferPos;
649     final int oldLimit = currentLimit;
650     if (byteLimit > oldLimit) {
651       throw InvalidProtocolBufferException.truncatedMessage();
652     }
653     currentLimit = byteLimit;
654
655     recomputeBufferSizeAfterLimit();
656
657     return oldLimit;
658   }
659
660   private void recomputeBufferSizeAfterLimit() {
661     bufferSize += bufferSizeAfterLimit;
662     final int bufferEnd = totalBytesRetired + bufferSize;
663     if (bufferEnd > currentLimit) {
664       // Limit is in current buffer.
665       bufferSizeAfterLimit = bufferEnd - currentLimit;
666       bufferSize -= bufferSizeAfterLimit;
667     } else {
668       bufferSizeAfterLimit = 0;
669     }
670   }
671
672   /**
673    * Discards the current limit, returning to the previous limit.
674    *
675    * @param oldLimit The old limit, as returned by {@code pushLimit}.
676    */
677   public void popLimit(final int oldLimit) {
678     currentLimit = oldLimit;
679     recomputeBufferSizeAfterLimit();
680   }
681
682   /**
683    * Returns the number of bytes to be read before the current limit.
684    * If no limit is set, returns -1.
685    */
686   public int getBytesUntilLimit() {
687     if (currentLimit == Integer.MAX_VALUE) {
688       return -1;
689     }
690
691     final int currentAbsolutePosition = totalBytesRetired + bufferPos;
692     return currentLimit - currentAbsolutePosition;
693   }
694
695   /**
696    * Returns true if the stream has reached the end of the input.  This is the
697    * case if either the end of the underlying input source has been reached or
698    * if the stream has reached a limit created using {@link #pushLimit(int)}.
699    */
700   public boolean isAtEnd() throws IOException {
701     return bufferPos == bufferSize && !refillBuffer(false);
702   }
703
704   /**
705    * The total bytes read up to the current position. Calling
706    * {@link #resetSizeCounter()} resets this value to zero.
707    */
708   public int getTotalBytesRead() {
709       return totalBytesRetired + bufferPos;
710   }
711
712   /**
713    * Called with {@code this.buffer} is empty to read more bytes from the
714    * input.  If {@code mustSucceed} is true, refillBuffer() guarantees that
715    * either there will be at least one byte in the buffer when it returns
716    * or it will throw an exception.  If {@code mustSucceed} is false,
717    * refillBuffer() returns false if no more bytes were available.
718    */
719   private boolean refillBuffer(final boolean mustSucceed) throws IOException {
720     if (bufferPos < bufferSize) {
721       throw new IllegalStateException(
722         "refillBuffer() called when buffer wasn't empty.");
723     }
724
725     if (totalBytesRetired + bufferSize == currentLimit) {
726       // Oops, we hit a limit.
727       if (mustSucceed) {
728         throw InvalidProtocolBufferException.truncatedMessage();
729       } else {
730         return false;
731       }
732     }
733
734     totalBytesRetired += bufferSize;
735
736     bufferPos = 0;
737     bufferSize = (input == null) ? -1 : input.read(buffer);
738     if (bufferSize == 0 || bufferSize < -1) {
739       throw new IllegalStateException(
740           "InputStream#read(byte[]) returned invalid result: " + bufferSize +
741           "\nThe InputStream implementation is buggy.");
742     }
743     if (bufferSize == -1) {
744       bufferSize = 0;
745       if (mustSucceed) {
746         throw InvalidProtocolBufferException.truncatedMessage();
747       } else {
748         return false;
749       }
750     } else {
751       recomputeBufferSizeAfterLimit();
752       final int totalBytesRead =
753         totalBytesRetired + bufferSize + bufferSizeAfterLimit;
754       if (totalBytesRead > sizeLimit || totalBytesRead < 0) {
755         throw InvalidProtocolBufferException.sizeLimitExceeded();
756       }
757       return true;
758     }
759   }
760
761   /**
762    * Read one byte from the input.
763    *
764    * @throws InvalidProtocolBufferException The end of the stream or the current
765    *                                        limit was reached.
766    */
767   public byte readRawByte() throws IOException {
768     if (bufferPos == bufferSize) {
769       refillBuffer(true);
770     }
771     return buffer[bufferPos++];
772   }
773
774   /**
775    * Read a fixed size of bytes from the input.
776    *
777    * @throws InvalidProtocolBufferException The end of the stream or the current
778    *                                        limit was reached.
779    */
780   public byte[] readRawBytes(final int size) throws IOException {
781     if (size < 0) {
782       throw InvalidProtocolBufferException.negativeSize();
783     }
784
785     if (totalBytesRetired + bufferPos + size > currentLimit) {
786       // Read to the end of the stream anyway.
787       skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
788       // Then fail.
789       throw InvalidProtocolBufferException.truncatedMessage();
790     }
791
792     if (size <= bufferSize - bufferPos) {
793       // We have all the bytes we need already.
794       final byte[] bytes = new byte[size];
795       System.arraycopy(buffer, bufferPos, bytes, 0, size);
796       bufferPos += size;
797       return bytes;
798     } else if (size < BUFFER_SIZE) {
799       // Reading more bytes than are in the buffer, but not an excessive number
800       // of bytes.  We can safely allocate the resulting array ahead of time.
801
802       // First copy what we have.
803       final byte[] bytes = new byte[size];
804       int pos = bufferSize - bufferPos;
805       System.arraycopy(buffer, bufferPos, bytes, 0, pos);
806       bufferPos = bufferSize;
807
808       // We want to use refillBuffer() and then copy from the buffer into our
809       // byte array rather than reading directly into our byte array because
810       // the input may be unbuffered.
811       refillBuffer(true);
812
813       while (size - pos > bufferSize) {
814         System.arraycopy(buffer, 0, bytes, pos, bufferSize);
815         pos += bufferSize;
816         bufferPos = bufferSize;
817         refillBuffer(true);
818       }
819
820       System.arraycopy(buffer, 0, bytes, pos, size - pos);
821       bufferPos = size - pos;
822
823       return bytes;
824     } else {
825       // The size is very large.  For security reasons, we can't allocate the
826       // entire byte array yet.  The size comes directly from the input, so a
827       // maliciously-crafted message could provide a bogus very large size in
828       // order to trick the app into allocating a lot of memory.  We avoid this
829       // by allocating and reading only a small chunk at a time, so that the
830       // malicious message must actually *be* extremely large to cause
831       // problems.  Meanwhile, we limit the allowed size of a message elsewhere.
832
833       // Remember the buffer markers since we'll have to copy the bytes out of
834       // it later.
835       final int originalBufferPos = bufferPos;
836       final int originalBufferSize = bufferSize;
837
838       // Mark the current buffer consumed.
839       totalBytesRetired += bufferSize;
840       bufferPos = 0;
841       bufferSize = 0;
842
843       // Read all the rest of the bytes we need.
844       int sizeLeft = size - (originalBufferSize - originalBufferPos);
845       final List<byte[]> chunks = new ArrayList<byte[]>();
846
847       while (sizeLeft > 0) {
848         final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
849         int pos = 0;
850         while (pos < chunk.length) {
851           final int n = (input == null) ? -1 :
852             input.read(chunk, pos, chunk.length - pos);
853           if (n == -1) {
854             throw InvalidProtocolBufferException.truncatedMessage();
855           }
856           totalBytesRetired += n;
857           pos += n;
858         }
859         sizeLeft -= chunk.length;
860         chunks.add(chunk);
861       }
862
863       // OK, got everything.  Now concatenate it all into one buffer.
864       final byte[] bytes = new byte[size];
865
866       // Start by copying the leftover bytes from this.buffer.
867       int pos = originalBufferSize - originalBufferPos;
868       System.arraycopy(buffer, originalBufferPos, bytes, 0, pos);
869
870       // And now all the chunks.
871       for (final byte[] chunk : chunks) {
872         System.arraycopy(chunk, 0, bytes, pos, chunk.length);
873         pos += chunk.length;
874       }
875
876       // Done.
877       return bytes;
878     }
879   }
880
881   /**
882    * Reads and discards {@code size} bytes.
883    *
884    * @throws InvalidProtocolBufferException The end of the stream or the current
885    *                                        limit was reached.
886    */
887   public void skipRawBytes(final int size) throws IOException {
888     if (size < 0) {
889       throw InvalidProtocolBufferException.negativeSize();
890     }
891
892     if (totalBytesRetired + bufferPos + size > currentLimit) {
893       // Read to the end of the stream anyway.
894       skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
895       // Then fail.
896       throw InvalidProtocolBufferException.truncatedMessage();
897     }
898
899     if (size <= bufferSize - bufferPos) {
900       // We have all the bytes we need already.
901       bufferPos += size;
902     } else {
903       // Skipping more bytes than are in the buffer.  First skip what we have.
904       int pos = bufferSize - bufferPos;
905       bufferPos = bufferSize;
906
907       // Keep refilling the buffer until we get to the point we wanted to skip
908       // to.  This has the side effect of ensuring the limits are updated
909       // correctly.
910       refillBuffer(true);
911       while (size - pos > bufferSize) {
912         pos += bufferSize;
913         bufferPos = bufferSize;
914         refillBuffer(true);
915       }
916
917       bufferPos = size - pos;
918     }
919   }
920 }