Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(143)

Side by Side Diff: third_party/protobuf/java/core/src/main/java/com/google/protobuf/CodedInputStream.java

Issue 2599263002: third_party/protobuf: Update to HEAD (f52e188fe4) (Closed)
Patch Set: Address comments Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Protocol Buffers - Google's data interchange format 1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved. 2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/ 3 // https://developers.google.com/protocol-buffers/
4 // 4 //
5 // Redistribution and use in source and binary forms, with or without 5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are 6 // modification, are permitted provided that the following conditions are
7 // met: 7 // met:
8 // 8 //
9 // * Redistributions of source code must retain the above copyright 9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer. 10 // notice, this list of conditions and the following disclaimer.
(...skipping 12 matching lines...) Expand all
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 30
31 package com.google.protobuf; 31 package com.google.protobuf;
32 32
33 import static com.google.protobuf.Internal.EMPTY_BYTE_ARRAY;
34 import static com.google.protobuf.Internal.EMPTY_BYTE_BUFFER;
35 import static com.google.protobuf.Internal.UTF_8;
36 import static com.google.protobuf.Internal.checkNotNull;
37 import static com.google.protobuf.WireFormat.FIXED_32_SIZE;
38 import static com.google.protobuf.WireFormat.FIXED_64_SIZE;
39 import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE;
40
33 import java.io.ByteArrayOutputStream; 41 import java.io.ByteArrayOutputStream;
34 import java.io.IOException; 42 import java.io.IOException;
35 import java.io.InputStream; 43 import java.io.InputStream;
36 import java.nio.ByteBuffer; 44 import java.nio.ByteBuffer;
37 import java.util.ArrayList; 45 import java.util.ArrayList;
38 import java.util.Arrays; 46 import java.util.Arrays;
39 import java.util.List; 47 import java.util.List;
40 48
41 /** 49 /**
42 * Reads and decodes protocol message fields. 50 * Reads and decodes protocol message fields.
43 * 51 *
44 * This class contains two kinds of methods: methods that read specific 52 * <p>This class contains two kinds of methods: methods that read specific proto col message
45 * protocol message constructs and field types (e.g. {@link #readTag()} and 53 * constructs and field types (e.g. {@link #readTag()} and {@link #readInt32()}) and methods that
46 * {@link #readInt32()}) and methods that read low-level values (e.g. 54 * read low-level values (e.g. {@link #readRawVarint32()} and {@link #readRawByt es}). If you are
47 * {@link #readRawVarint32()} and {@link #readRawBytes}). If you are reading 55 * reading encoded protocol messages, you should use the former methods, but if you are reading some
48 * encoded protocol messages, you should use the former methods, but if you are 56 * other format of your own design, use the latter.
49 * reading some other format of your own design, use the latter.
50 * 57 *
51 * @author kenton@google.com Kenton Varda 58 * @author kenton@google.com Kenton Varda
52 */ 59 */
53 public final class CodedInputStream { 60 public abstract class CodedInputStream {
54 /** 61 private static final int DEFAULT_BUFFER_SIZE = 4096;
55 * Create a new CodedInputStream wrapping the given InputStream. 62 private static final int DEFAULT_RECURSION_LIMIT = 100;
56 */ 63 // Integer.MAX_VALUE == 0x7FFFFFF == INT_MAX from limits.h
64 private static final int DEFAULT_SIZE_LIMIT = Integer.MAX_VALUE;
65
66 /** Visible for subclasses. See setRecursionLimit() */
67 int recursionDepth;
68
69 int recursionLimit = DEFAULT_RECURSION_LIMIT;
70
71 /** Visible for subclasses. See setSizeLimit() */
72 int sizeLimit = DEFAULT_SIZE_LIMIT;
73
74 /** Create a new CodedInputStream wrapping the given InputStream. */
57 public static CodedInputStream newInstance(final InputStream input) { 75 public static CodedInputStream newInstance(final InputStream input) {
58 return new CodedInputStream(input, BUFFER_SIZE); 76 return newInstance(input, DEFAULT_BUFFER_SIZE);
59 }
60
61 /**
62 * Create a new CodedInputStream wrapping the given InputStream.
63 */
64 static CodedInputStream newInstance(final InputStream input, int bufferSize) {
65 return new CodedInputStream(input, bufferSize);
66 } 77 }
67 78
68 /** 79 /** Create a new CodedInputStream wrapping the given InputStream. */
69 * Create a new CodedInputStream wrapping the given byte array. 80 static CodedInputStream newInstance(final InputStream input, int bufferSize) {
70 */ 81 if (input == null) {
82 // TODO(nathanmittler): Ideally we should throw here. This is done for bac kward compatibility.
83 return newInstance(EMPTY_BYTE_ARRAY);
84 }
85 return new StreamDecoder(input, bufferSize);
86 }
87
88 /** Create a new CodedInputStream wrapping the given byte array. */
71 public static CodedInputStream newInstance(final byte[] buf) { 89 public static CodedInputStream newInstance(final byte[] buf) {
72 return newInstance(buf, 0, buf.length); 90 return newInstance(buf, 0, buf.length);
73 } 91 }
74 92
75 /** 93 /** Create a new CodedInputStream wrapping the given byte array slice. */
76 * Create a new CodedInputStream wrapping the given byte array slice. 94 public static CodedInputStream newInstance(final byte[] buf, final int off, fi nal int len) {
77 */
78 public static CodedInputStream newInstance(final byte[] buf, final int off,
79 final int len) {
80 return newInstance(buf, off, len, false /* bufferIsImmutable */); 95 return newInstance(buf, off, len, false /* bufferIsImmutable */);
81 } 96 }
82 97
83 /** 98 /** Create a new CodedInputStream wrapping the given byte array slice. */
84 * Create a new CodedInputStream wrapping the given byte array slice.
85 */
86 static CodedInputStream newInstance( 99 static CodedInputStream newInstance(
87 final byte[] buf, final int off, final int len, final boolean bufferIsImmu table) { 100 final byte[] buf, final int off, final int len, final boolean bufferIsImmu table) {
88 CodedInputStream result = new CodedInputStream(buf, off, len, bufferIsImmuta ble); 101 ArrayDecoder result = new ArrayDecoder(buf, off, len, bufferIsImmutable);
89 try { 102 try {
90 // Some uses of CodedInputStream can be more efficient if they know 103 // Some uses of CodedInputStream can be more efficient if they know
91 // exactly how many bytes are available. By pushing the end point of the 104 // exactly how many bytes are available. By pushing the end point of the
92 // buffer as a limit, we allow them to get this information via 105 // buffer as a limit, we allow them to get this information via
93 // getBytesUntilLimit(). Pushing a limit that we know is at the end of 106 // getBytesUntilLimit(). Pushing a limit that we know is at the end of
94 // the stream can never hurt, since we can never past that point anyway. 107 // the stream can never hurt, since we can never past that point anyway.
95 result.pushLimit(len); 108 result.pushLimit(len);
96 } catch (InvalidProtocolBufferException ex) { 109 } catch (InvalidProtocolBufferException ex) {
97 // The only reason pushLimit() might throw an exception here is if len 110 // The only reason pushLimit() might throw an exception here is if len
98 // is negative. Normally pushLimit()'s parameter comes directly off the 111 // is negative. Normally pushLimit()'s parameter comes directly off the
99 // wire, so it's important to catch exceptions in case of corrupt or 112 // wire, so it's important to catch exceptions in case of corrupt or
100 // malicious data. However, in this case, we expect that len is not a 113 // malicious data. However, in this case, we expect that len is not a
101 // user-supplied value, so we can assume that it being negative indicates 114 // user-supplied value, so we can assume that it being negative indicates
102 // a programming error. Therefore, throwing an unchecked exception is 115 // a programming error. Therefore, throwing an unchecked exception is
103 // appropriate. 116 // appropriate.
104 throw new IllegalArgumentException(ex); 117 throw new IllegalArgumentException(ex);
105 } 118 }
106 return result; 119 return result;
107 } 120 }
108 121
109 /** 122 /**
110 * Create a new CodedInputStream wrapping the given ByteBuffer. The data 123 * Create a new CodedInputStream wrapping the given ByteBuffer. The data start ing from the
111 * starting from the ByteBuffer's current position to its limit will be read. 124 * ByteBuffer's current position to its limit will be read. The returned Coded InputStream may or
112 * The returned CodedInputStream may or may not share the underlying data 125 * may not share the underlying data in the ByteBuffer, therefore the ByteBuff er cannot be changed
113 * in the ByteBuffer, therefore the ByteBuffer cannot be changed while the 126 * while the CodedInputStream is in use. Note that the ByteBuffer's position w on't be changed by
114 * CodedInputStream is in use. 127 * this function. Concurrent calls with the same ByteBuffer object are safe if no other thread is
115 * Note that the ByteBuffer's position won't be changed by this function. 128 * trying to alter the ByteBuffer's status.
116 * Concurrent calls with the same ByteBuffer object are safe if no other
117 * thread is trying to alter the ByteBuffer's status.
118 */ 129 */
119 public static CodedInputStream newInstance(ByteBuffer buf) { 130 public static CodedInputStream newInstance(ByteBuffer buf) {
131 return newInstance(buf, false /* bufferIsImmutable */);
132 }
133
134 /** Create a new CodedInputStream wrapping the given buffer. */
135 static CodedInputStream newInstance(ByteBuffer buf, boolean bufferIsImmutable) {
120 if (buf.hasArray()) { 136 if (buf.hasArray()) {
121 return newInstance(buf.array(), buf.arrayOffset() + buf.position(), 137 return newInstance(
122 buf.remaining()); 138 buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), buff erIsImmutable);
123 } else {
124 ByteBuffer temp = buf.duplicate();
125 byte[] buffer = new byte[temp.remaining()];
126 temp.get(buffer);
127 return newInstance(buffer);
128 } 139 }
140
141 if (buf.isDirect() && UnsafeDirectNioDecoder.isSupported()) {
142 return new UnsafeDirectNioDecoder(buf, bufferIsImmutable);
143 }
144
145 // The buffer is non-direct and does not expose the underlying array. Using the ByteBuffer API
146 // to access individual bytes is very slow, so just copy the buffer to an ar ray.
147 // TODO(nathanmittler): Re-evaluate with Java 9
148 byte[] buffer = new byte[buf.remaining()];
149 buf.duplicate().get(buffer);
150 return newInstance(buffer, 0, buffer.length, true);
129 } 151 }
130 152
153 /** Disable construction/inheritance outside of this class. */
154 private CodedInputStream() {}
155
131 // ----------------------------------------------------------------- 156 // -----------------------------------------------------------------
132 157
133 /** 158 /**
134 * Attempt to read a field tag, returning zero if we have reached EOF. 159 * Attempt to read a field tag, returning zero if we have reached EOF. Protoco l message parsers
135 * Protocol message parsers use this to read tags, since a protocol message 160 * use this to read tags, since a protocol message may legally end wherever a tag occurs, and zero
136 * may legally end wherever a tag occurs, and zero is not a valid tag number. 161 * is not a valid tag number.
137 */ 162 */
138 public int readTag() throws IOException { 163 public abstract int readTag() throws IOException;
139 if (isAtEnd()) { 164
140 lastTag = 0; 165 /**
141 return 0; 166 * Verifies that the last call to readTag() returned the given tag value. This is used to verify
142 } 167 * that a nested group ended with the correct end tag.
143 168 *
144 lastTag = readRawVarint32(); 169 * @throws InvalidProtocolBufferException {@code value} does not match the las t tag.
145 if (WireFormat.getTagFieldNumber(lastTag) == 0) { 170 */
146 // If we actually read zero (or any tag number corresponding to field 171 public abstract void checkLastTagWas(final int value) throws InvalidProtocolBu fferException;
147 // number zero), that's not a valid tag. 172
148 throw InvalidProtocolBufferException.invalidTag(); 173 public abstract int getLastTag();
149 }
150 return lastTag;
151 }
152
153 /**
154 * Verifies that the last call to readTag() returned the given tag value.
155 * This is used to verify that a nested group ended with the correct
156 * end tag.
157 *
158 * @throws InvalidProtocolBufferException {@code value} does not match the
159 * last tag.
160 */
161 public void checkLastTagWas(final int value)
162 throws InvalidProtocolBufferException {
163 if (lastTag != value) {
164 throw InvalidProtocolBufferException.invalidEndTag();
165 }
166 }
167
168 public int getLastTag() {
169 return lastTag;
170 }
171 174
172 /** 175 /**
173 * Reads and discards a single field, given its tag value. 176 * Reads and discards a single field, given its tag value.
174 * 177 *
175 * @return {@code false} if the tag is an endgroup tag, in which case 178 * @return {@code false} if the tag is an endgroup tag, in which case nothing is skipped.
176 * nothing is skipped. Otherwise, returns {@code true}. 179 * Otherwise, returns {@code true}.
177 */ 180 */
178 public boolean skipField(final int tag) throws IOException { 181 public abstract boolean skipField(final int tag) throws IOException;
179 switch (WireFormat.getTagWireType(tag)) { 182
180 case WireFormat.WIRETYPE_VARINT: 183 /**
181 skipRawVarint(); 184 * Reads a single field and writes it to output in wire format, given its tag value.
182 return true; 185 *
183 case WireFormat.WIRETYPE_FIXED64: 186 * @return {@code false} if the tag is an endgroup tag, in which case nothing is skipped.
184 skipRawBytes(8); 187 * Otherwise, returns {@code true}.
185 return true; 188 * @deprecated use {@code UnknownFieldSet} or {@code UnknownFieldSetLite} to s kip to an output
186 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 189 * stream.
187 skipRawBytes(readRawVarint32()); 190 */
188 return true; 191 @Deprecated
189 case WireFormat.WIRETYPE_START_GROUP: 192 public abstract boolean skipField(final int tag, final CodedOutputStream outpu t)
190 skipMessage(); 193 throws IOException;
191 checkLastTagWas( 194
192 WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), 195 /**
193 WireFormat.WIRETYPE_END_GROUP)); 196 * Reads and discards an entire message. This will read either until EOF or un til an endgroup tag,
194 return true; 197 * whichever comes first.
195 case WireFormat.WIRETYPE_END_GROUP: 198 */
196 return false; 199 public abstract void skipMessage() throws IOException;
197 case WireFormat.WIRETYPE_FIXED32: 200
198 skipRawBytes(4); 201 /**
199 return true; 202 * Reads an entire message and writes it to output in wire format. This will r ead either until EOF
200 default:
201 throw InvalidProtocolBufferException.invalidWireType();
202 }
203 }
204
205 /**
206 * Reads a single field and writes it to output in wire format,
207 * given its tag value.
208 *
209 * @return {@code false} if the tag is an endgroup tag, in which case
210 * nothing is skipped. Otherwise, returns {@code true}.
211 */
212 public boolean skipField(final int tag, final CodedOutputStream output)
213 throws IOException {
214 switch (WireFormat.getTagWireType(tag)) {
215 case WireFormat.WIRETYPE_VARINT: {
216 long value = readInt64();
217 output.writeRawVarint32(tag);
218 output.writeUInt64NoTag(value);
219 return true;
220 }
221 case WireFormat.WIRETYPE_FIXED64: {
222 long value = readRawLittleEndian64();
223 output.writeRawVarint32(tag);
224 output.writeFixed64NoTag(value);
225 return true;
226 }
227 case WireFormat.WIRETYPE_LENGTH_DELIMITED: {
228 ByteString value = readBytes();
229 output.writeRawVarint32(tag);
230 output.writeBytesNoTag(value);
231 return true;
232 }
233 case WireFormat.WIRETYPE_START_GROUP: {
234 output.writeRawVarint32(tag);
235 skipMessage(output);
236 int endtag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag),
237 WireFormat.WIRETYPE_END_GROUP);
238 checkLastTagWas(endtag);
239 output.writeRawVarint32(endtag);
240 return true;
241 }
242 case WireFormat.WIRETYPE_END_GROUP: {
243 return false;
244 }
245 case WireFormat.WIRETYPE_FIXED32: {
246 int value = readRawLittleEndian32();
247 output.writeRawVarint32(tag);
248 output.writeFixed32NoTag(value);
249 return true;
250 }
251 default:
252 throw InvalidProtocolBufferException.invalidWireType();
253 }
254 }
255
256 /**
257 * Reads and discards an entire message. This will read either until EOF
258 * or until an endgroup tag, whichever comes first. 203 * or until an endgroup tag, whichever comes first.
259 */ 204 */
260 public void skipMessage() throws IOException { 205 public abstract void skipMessage(CodedOutputStream output) throws IOException;
261 while (true) {
262 final int tag = readTag();
263 if (tag == 0 || !skipField(tag)) {
264 return;
265 }
266 }
267 }
268
269 /**
270 * Reads an entire message and writes it to output in wire format.
271 * This will read either until EOF or until an endgroup tag,
272 * whichever comes first.
273 */
274 public void skipMessage(CodedOutputStream output) throws IOException {
275 while (true) {
276 final int tag = readTag();
277 if (tag == 0 || !skipField(tag, output)) {
278 return;
279 }
280 }
281 }
282
283 /**
284 * Collects the bytes skipped and returns the data in a ByteBuffer.
285 */
286 private class SkippedDataSink implements RefillCallback {
287 private int lastPos = bufferPos;
288 private ByteArrayOutputStream byteArrayStream;
289
290 @Override
291 public void onRefill() {
292 if (byteArrayStream == null) {
293 byteArrayStream = new ByteArrayOutputStream();
294 }
295 byteArrayStream.write(buffer, lastPos, bufferPos - lastPos);
296 lastPos = 0;
297 }
298
299 /**
300 * Gets skipped data in a ByteBuffer. This method should only be
301 * called once.
302 */
303 ByteBuffer getSkippedData() {
304 if (byteArrayStream == null) {
305 return ByteBuffer.wrap(buffer, lastPos, bufferPos - lastPos);
306 } else {
307 byteArrayStream.write(buffer, lastPos, bufferPos);
308 return ByteBuffer.wrap(byteArrayStream.toByteArray());
309 }
310 }
311 }
312 206
313 207
314 // ----------------------------------------------------------------- 208 // -----------------------------------------------------------------
315 209
316 /** Read a {@code double} field value from the stream. */ 210 /** Read a {@code double} field value from the stream. */
317 public double readDouble() throws IOException { 211 public abstract double readDouble() throws IOException;
318 return Double.longBitsToDouble(readRawLittleEndian64());
319 }
320 212
321 /** Read a {@code float} field value from the stream. */ 213 /** Read a {@code float} field value from the stream. */
322 public float readFloat() throws IOException { 214 public abstract float readFloat() throws IOException;
323 return Float.intBitsToFloat(readRawLittleEndian32());
324 }
325 215
326 /** Read a {@code uint64} field value from the stream. */ 216 /** Read a {@code uint64} field value from the stream. */
327 public long readUInt64() throws IOException { 217 public abstract long readUInt64() throws IOException;
328 return readRawVarint64();
329 }
330 218
331 /** Read an {@code int64} field value from the stream. */ 219 /** Read an {@code int64} field value from the stream. */
332 public long readInt64() throws IOException { 220 public abstract long readInt64() throws IOException;
333 return readRawVarint64();
334 }
335 221
336 /** Read an {@code int32} field value from the stream. */ 222 /** Read an {@code int32} field value from the stream. */
337 public int readInt32() throws IOException { 223 public abstract int readInt32() throws IOException;
338 return readRawVarint32();
339 }
340 224
341 /** Read a {@code fixed64} field value from the stream. */ 225 /** Read a {@code fixed64} field value from the stream. */
342 public long readFixed64() throws IOException { 226 public abstract long readFixed64() throws IOException;
343 return readRawLittleEndian64();
344 }
345 227
346 /** Read a {@code fixed32} field value from the stream. */ 228 /** Read a {@code fixed32} field value from the stream. */
347 public int readFixed32() throws IOException { 229 public abstract int readFixed32() throws IOException;
348 return readRawLittleEndian32();
349 }
350 230
351 /** Read a {@code bool} field value from the stream. */ 231 /** Read a {@code bool} field value from the stream. */
352 public boolean readBool() throws IOException { 232 public abstract boolean readBool() throws IOException;
353 return readRawVarint64() != 0; 233
354 } 234 /**
355 235 * Read a {@code string} field value from the stream. If the stream contains m alformed UTF-8,
356 /**
357 * Read a {@code string} field value from the stream.
358 * If the stream contains malformed UTF-8,
359 * replace the offending bytes with the standard UTF-8 replacement character. 236 * replace the offending bytes with the standard UTF-8 replacement character.
360 */ 237 */
361 public String readString() throws IOException { 238 public abstract String readString() throws IOException;
362 final int size = readRawVarint32(); 239
363 if (size <= (bufferSize - bufferPos) && size > 0) { 240 /**
364 // Fast path: We already have the bytes in a contiguous buffer, so 241 * Read a {@code string} field value from the stream. If the stream contains m alformed UTF-8,
365 // just copy directly from it.
366 final String result = new String(buffer, bufferPos, size, Internal.UTF_8);
367 bufferPos += size;
368 return result;
369 } else if (size == 0) {
370 return "";
371 } else if (size <= bufferSize) {
372 refillBuffer(size);
373 String result = new String(buffer, bufferPos, size, Internal.UTF_8);
374 bufferPos += size;
375 return result;
376 } else {
377 // Slow path: Build a byte array first then copy it.
378 return new String(readRawBytesSlowPath(size), Internal.UTF_8);
379 }
380 }
381
382 /**
383 * Read a {@code string} field value from the stream.
384 * If the stream contains malformed UTF-8,
385 * throw exception {@link InvalidProtocolBufferException}. 242 * throw exception {@link InvalidProtocolBufferException}.
386 */ 243 */
387 public String readStringRequireUtf8() throws IOException { 244 public abstract String readStringRequireUtf8() throws IOException;
388 final int size = readRawVarint32();
389 final byte[] bytes;
390 final int oldPos = bufferPos;
391 final int pos;
392 if (size <= (bufferSize - oldPos) && size > 0) {
393 // Fast path: We already have the bytes in a contiguous buffer, so
394 // just copy directly from it.
395 bytes = buffer;
396 bufferPos = oldPos + size;
397 pos = oldPos;
398 } else if (size == 0) {
399 return "";
400 } else if (size <= bufferSize) {
401 refillBuffer(size);
402 bytes = buffer;
403 pos = 0;
404 bufferPos = pos + size;
405 } else {
406 // Slow path: Build a byte array first then copy it.
407 bytes = readRawBytesSlowPath(size);
408 pos = 0;
409 }
410 // TODO(martinrb): We could save a pass by validating while decoding.
411 if (!Utf8.isValidUtf8(bytes, pos, pos + size)) {
412 throw InvalidProtocolBufferException.invalidUtf8();
413 }
414 return new String(bytes, pos, size, Internal.UTF_8);
415 }
416 245
417 /** Read a {@code group} field value from the stream. */ 246 /** Read a {@code group} field value from the stream. */
418 public void readGroup(final int fieldNumber, 247 public abstract void readGroup(
419 final MessageLite.Builder builder, 248 final int fieldNumber,
420 final ExtensionRegistryLite extensionRegistry) 249 final MessageLite.Builder builder,
421 throws IOException { 250 final ExtensionRegistryLite extensionRegistry)
422 if (recursionDepth >= recursionLimit) { 251 throws IOException;
423 throw InvalidProtocolBufferException.recursionLimitExceeded();
424 }
425 ++recursionDepth;
426 builder.mergeFrom(this, extensionRegistry);
427 checkLastTagWas(
428 WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
429 --recursionDepth;
430 }
431 252
432 253
433 /** Read a {@code group} field value from the stream. */ 254 /** Read a {@code group} field value from the stream. */
434 public <T extends MessageLite> T readGroup( 255 public abstract <T extends MessageLite> T readGroup(
435 final int fieldNumber, 256 final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)
436 final Parser<T> parser, 257 throws IOException;
437 final ExtensionRegistryLite extensionRegistry) 258
438 throws IOException { 259 /**
439 if (recursionDepth >= recursionLimit) { 260 * Reads a {@code group} field value from the stream and merges it into the gi ven {@link
440 throw InvalidProtocolBufferException.recursionLimitExceeded(); 261 * UnknownFieldSet}.
441 } 262 *
442 ++recursionDepth; 263 * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so you can just call
443 T result = parser.parsePartialFrom(this, extensionRegistry); 264 * {@link #readGroup}.
444 checkLastTagWas(
445 WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
446 --recursionDepth;
447 return result;
448 }
449
450 /**
451 * Reads a {@code group} field value from the stream and merges it into the
452 * given {@link UnknownFieldSet}.
453 *
454 * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so
455 * you can just call {@link #readGroup}.
456 */ 265 */
457 @Deprecated 266 @Deprecated
458 public void readUnknownGroup(final int fieldNumber, 267 public abstract void readUnknownGroup(final int fieldNumber, final MessageLite .Builder builder)
459 final MessageLite.Builder builder) 268 throws IOException;
460 throws IOException {
461 // We know that UnknownFieldSet will ignore any ExtensionRegistry so it
462 // is safe to pass null here. (We can't call
463 // ExtensionRegistry.getEmptyRegistry() because that would make this
464 // class depend on ExtensionRegistry, which is not part of the lite
465 // library.)
466 readGroup(fieldNumber, builder, null);
467 }
468 269
469 /** Read an embedded message field value from the stream. */ 270 /** Read an embedded message field value from the stream. */
470 public void readMessage(final MessageLite.Builder builder, 271 public abstract void readMessage(
471 final ExtensionRegistryLite extensionRegistry) 272 final MessageLite.Builder builder, final ExtensionRegistryLite extensionRe gistry)
472 throws IOException { 273 throws IOException;
473 final int length = readRawVarint32();
474 if (recursionDepth >= recursionLimit) {
475 throw InvalidProtocolBufferException.recursionLimitExceeded();
476 }
477 final int oldLimit = pushLimit(length);
478 ++recursionDepth;
479 builder.mergeFrom(this, extensionRegistry);
480 checkLastTagWas(0);
481 --recursionDepth;
482 popLimit(oldLimit);
483 }
484 274
485 275
486 /** Read an embedded message field value from the stream. */ 276 /** Read an embedded message field value from the stream. */
487 public <T extends MessageLite> T readMessage( 277 public abstract <T extends MessageLite> T readMessage(
488 final Parser<T> parser, 278 final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) thr ows IOException;
489 final ExtensionRegistryLite extensionRegistry)
490 throws IOException {
491 int length = readRawVarint32();
492 if (recursionDepth >= recursionLimit) {
493 throw InvalidProtocolBufferException.recursionLimitExceeded();
494 }
495 final int oldLimit = pushLimit(length);
496 ++recursionDepth;
497 T result = parser.parsePartialFrom(this, extensionRegistry);
498 checkLastTagWas(0);
499 --recursionDepth;
500 popLimit(oldLimit);
501 return result;
502 }
503 279
504 /** Read a {@code bytes} field value from the stream. */ 280 /** Read a {@code bytes} field value from the stream. */
505 public ByteString readBytes() throws IOException { 281 public abstract ByteString readBytes() throws IOException;
506 final int size = readRawVarint32();
507 if (size <= (bufferSize - bufferPos) && size > 0) {
508 // Fast path: We already have the bytes in a contiguous buffer, so
509 // just copy directly from it.
510 final ByteString result = bufferIsImmutable && enableAliasing
511 ? ByteString.wrap(buffer, bufferPos, size)
512 : ByteString.copyFrom(buffer, bufferPos, size);
513 bufferPos += size;
514 return result;
515 } else if (size == 0) {
516 return ByteString.EMPTY;
517 } else {
518 // Slow path: Build a byte array first then copy it.
519 return ByteString.wrap(readRawBytesSlowPath(size));
520 }
521 }
522 282
523 /** Read a {@code bytes} field value from the stream. */ 283 /** Read a {@code bytes} field value from the stream. */
524 public byte[] readByteArray() throws IOException { 284 public abstract byte[] readByteArray() throws IOException;
525 final int size = readRawVarint32();
526 if (size <= (bufferSize - bufferPos) && size > 0) {
527 // Fast path: We already have the bytes in a contiguous buffer, so
528 // just copy directly from it.
529 final byte[] result =
530 Arrays.copyOfRange(buffer, bufferPos, bufferPos + size);
531 bufferPos += size;
532 return result;
533 } else {
534 // Slow path: Build a byte array first then copy it.
535 return readRawBytesSlowPath(size);
536 }
537 }
538 285
539 /** Read a {@code bytes} field value from the stream. */ 286 /** Read a {@code bytes} field value from the stream. */
540 public ByteBuffer readByteBuffer() throws IOException { 287 public abstract ByteBuffer readByteBuffer() throws IOException;
541 final int size = readRawVarint32();
542 if (size <= (bufferSize - bufferPos) && size > 0) {
543 // Fast path: We already have the bytes in a contiguous buffer.
544 // When aliasing is enabled, we can return a ByteBuffer pointing directly
545 // into the underlying byte array without copy if the CodedInputStream is
546 // constructed from a byte array. If aliasing is disabled or the input is
547 // from an InputStream or ByteString, we have to make a copy of the bytes.
548 ByteBuffer result = input == null && !bufferIsImmutable && enableAliasing
549 ? ByteBuffer.wrap(buffer, bufferPos, size).slice()
550 : ByteBuffer.wrap(Arrays.copyOfRange(
551 buffer, bufferPos, bufferPos + size));
552 bufferPos += size;
553 return result;
554 } else if (size == 0) {
555 return Internal.EMPTY_BYTE_BUFFER;
556 } else {
557 // Slow path: Build a byte array first then copy it.
558 return ByteBuffer.wrap(readRawBytesSlowPath(size));
559 }
560 }
561 288
562 /** Read a {@code uint32} field value from the stream. */ 289 /** Read a {@code uint32} field value from the stream. */
563 public int readUInt32() throws IOException { 290 public abstract int readUInt32() throws IOException;
564 return readRawVarint32(); 291
565 } 292 /**
566 293 * Read an enum field value from the stream. Caller is responsible for convert ing the numeric
567 /** 294 * value to an actual enum.
568 * Read an enum field value from the stream. Caller is responsible 295 */
569 * for converting the numeric value to an actual enum. 296 public abstract int readEnum() throws IOException;
570 */
571 public int readEnum() throws IOException {
572 return readRawVarint32();
573 }
574 297
575 /** Read an {@code sfixed32} field value from the stream. */ 298 /** Read an {@code sfixed32} field value from the stream. */
576 public int readSFixed32() throws IOException { 299 public abstract int readSFixed32() throws IOException;
577 return readRawLittleEndian32();
578 }
579 300
580 /** Read an {@code sfixed64} field value from the stream. */ 301 /** Read an {@code sfixed64} field value from the stream. */
581 public long readSFixed64() throws IOException { 302 public abstract long readSFixed64() throws IOException;
582 return readRawLittleEndian64();
583 }
584 303
585 /** Read an {@code sint32} field value from the stream. */ 304 /** Read an {@code sint32} field value from the stream. */
586 public int readSInt32() throws IOException { 305 public abstract int readSInt32() throws IOException;
587 return decodeZigZag32(readRawVarint32());
588 }
589 306
590 /** Read an {@code sint64} field value from the stream. */ 307 /** Read an {@code sint64} field value from the stream. */
591 public long readSInt64() throws IOException { 308 public abstract long readSInt64() throws IOException;
592 return decodeZigZag64(readRawVarint64());
593 }
594 309
595 // ================================================================= 310 // =================================================================
596 311
597 /** 312 /** Read a raw Varint from the stream. If larger than 32 bits, discard the upp er bits. */
598 * Read a raw Varint from the stream. If larger than 32 bits, discard the 313 public abstract int readRawVarint32() throws IOException;
599 * upper bits.
600 */
601 public int readRawVarint32() throws IOException {
602 // See implementation notes for readRawVarint64
603 fastpath: {
604 int pos = bufferPos;
605
606 if (bufferSize == pos) {
607 break fastpath;
608 }
609
610 final byte[] buffer = this.buffer;
611 int x;
612 if ((x = buffer[pos++]) >= 0) {
613 bufferPos = pos;
614 return x;
615 } else if (bufferSize - pos < 9) {
616 break fastpath;
617 } else if ((x ^= (buffer[pos++] << 7)) < 0) {
618 x ^= (~0 << 7);
619 } else if ((x ^= (buffer[pos++] << 14)) >= 0) {
620 x ^= (~0 << 7) ^ (~0 << 14);
621 } else if ((x ^= (buffer[pos++] << 21)) < 0) {
622 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
623 } else {
624 int y = buffer[pos++];
625 x ^= y << 28;
626 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
627 if (y < 0 &&
628 buffer[pos++] < 0 &&
629 buffer[pos++] < 0 &&
630 buffer[pos++] < 0 &&
631 buffer[pos++] < 0 &&
632 buffer[pos++] < 0) {
633 break fastpath; // Will throw malformedVarint()
634 }
635 }
636 bufferPos = pos;
637 return x;
638 }
639 return (int) readRawVarint64SlowPath();
640 }
641
642 private void skipRawVarint() throws IOException {
643 if (bufferSize - bufferPos >= 10) {
644 final byte[] buffer = this.buffer;
645 int pos = bufferPos;
646 for (int i = 0; i < 10; i++) {
647 if (buffer[pos++] >= 0) {
648 bufferPos = pos;
649 return;
650 }
651 }
652 }
653 skipRawVarintSlowPath();
654 }
655
656 private void skipRawVarintSlowPath() throws IOException {
657 for (int i = 0; i < 10; i++) {
658 if (readRawByte() >= 0) {
659 return;
660 }
661 }
662 throw InvalidProtocolBufferException.malformedVarint();
663 }
664
665 /**
666 * Reads a varint from the input one byte at a time, so that it does not
667 * read any bytes after the end of the varint. If you simply wrapped the
668 * stream in a CodedInputStream and used {@link #readRawVarint32(InputStream)}
669 * then you would probably end up reading past the end of the varint since
670 * CodedInputStream buffers its input.
671 */
672 static int readRawVarint32(final InputStream input) throws IOException {
673 final int firstByte = input.read();
674 if (firstByte == -1) {
675 throw InvalidProtocolBufferException.truncatedMessage();
676 }
677 return readRawVarint32(firstByte, input);
678 }
679
680 /**
681 * Like {@link #readRawVarint32(InputStream)}, but expects that the caller
682 * has already read one byte. This allows the caller to determine if EOF
683 * has been reached before attempting to read.
684 */
685 public static int readRawVarint32(
686 final int firstByte, final InputStream input) throws IOException {
687 if ((firstByte & 0x80) == 0) {
688 return firstByte;
689 }
690
691 int result = firstByte & 0x7f;
692 int offset = 7;
693 for (; offset < 32; offset += 7) {
694 final int b = input.read();
695 if (b == -1) {
696 throw InvalidProtocolBufferException.truncatedMessage();
697 }
698 result |= (b & 0x7f) << offset;
699 if ((b & 0x80) == 0) {
700 return result;
701 }
702 }
703 // Keep reading up to 64 bits.
704 for (; offset < 64; offset += 7) {
705 final int b = input.read();
706 if (b == -1) {
707 throw InvalidProtocolBufferException.truncatedMessage();
708 }
709 if ((b & 0x80) == 0) {
710 return result;
711 }
712 }
713 throw InvalidProtocolBufferException.malformedVarint();
714 }
715 314
716 /** Read a raw Varint from the stream. */ 315 /** Read a raw Varint from the stream. */
717 public long readRawVarint64() throws IOException { 316 public abstract long readRawVarint64() throws IOException;
718 // Implementation notes:
719 //
720 // Optimized for one-byte values, expected to be common.
721 // The particular code below was selected from various candidates
722 // empirically, by winning VarintBenchmark.
723 //
724 // Sign extension of (signed) Java bytes is usually a nuisance, but
725 // we exploit it here to more easily obtain the sign of bytes read.
726 // Instead of cleaning up the sign extension bits by masking eagerly,
727 // we delay until we find the final (positive) byte, when we clear all
728 // accumulated bits with one xor. We depend on javac to constant fold.
729 fastpath: {
730 int pos = bufferPos;
731
732 if (bufferSize == pos) {
733 break fastpath;
734 }
735
736 final byte[] buffer = this.buffer;
737 long x;
738 int y;
739 if ((y = buffer[pos++]) >= 0) {
740 bufferPos = pos;
741 return y;
742 } else if (bufferSize - pos < 9) {
743 break fastpath;
744 } else if ((y ^= (buffer[pos++] << 7)) < 0) {
745 x = y ^ (~0 << 7);
746 } else if ((y ^= (buffer[pos++] << 14)) >= 0) {
747 x = y ^ ((~0 << 7) ^ (~0 << 14));
748 } else if ((y ^= (buffer[pos++] << 21)) < 0) {
749 x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
750 } else if ((x = ((long) y) ^ ((long) buffer[pos++] << 28)) >= 0L) {
751 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
752 } else if ((x ^= ((long) buffer[pos++] << 35)) < 0L) {
753 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
754 } else if ((x ^= ((long) buffer[pos++] << 42)) >= 0L) {
755 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
756 } else if ((x ^= ((long) buffer[pos++] << 49)) < 0L) {
757 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42)
758 ^ (~0L << 49);
759 } else {
760 x ^= ((long) buffer[pos++] << 56);
761 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42)
762 ^ (~0L << 49) ^ (~0L << 56);
763 if (x < 0L) {
764 if (buffer[pos++] < 0L) {
765 break fastpath; // Will throw malformedVarint()
766 }
767 }
768 }
769 bufferPos = pos;
770 return x;
771 }
772 return readRawVarint64SlowPath();
773 }
774 317
775 /** Variant of readRawVarint64 for when uncomfortably close to the limit. */ 318 /** Variant of readRawVarint64 for when uncomfortably close to the limit. */
776 /* Visible for testing */ 319 /* Visible for testing */
777 long readRawVarint64SlowPath() throws IOException { 320 abstract long readRawVarint64SlowPath() throws IOException;
778 long result = 0;
779 for (int shift = 0; shift < 64; shift += 7) {
780 final byte b = readRawByte();
781 result |= (long) (b & 0x7F) << shift;
782 if ((b & 0x80) == 0) {
783 return result;
784 }
785 }
786 throw InvalidProtocolBufferException.malformedVarint();
787 }
788 321
789 /** Read a 32-bit little-endian integer from the stream. */ 322 /** Read a 32-bit little-endian integer from the stream. */
790 public int readRawLittleEndian32() throws IOException { 323 public abstract int readRawLittleEndian32() throws IOException;
791 int pos = bufferPos;
792
793 // hand-inlined ensureAvailable(4);
794 if (bufferSize - pos < 4) {
795 refillBuffer(4);
796 pos = bufferPos;
797 }
798
799 final byte[] buffer = this.buffer;
800 bufferPos = pos + 4;
801 return (((buffer[pos] & 0xff)) |
802 ((buffer[pos + 1] & 0xff) << 8) |
803 ((buffer[pos + 2] & 0xff) << 16) |
804 ((buffer[pos + 3] & 0xff) << 24));
805 }
806 324
807 /** Read a 64-bit little-endian integer from the stream. */ 325 /** Read a 64-bit little-endian integer from the stream. */
808 public long readRawLittleEndian64() throws IOException { 326 public abstract long readRawLittleEndian64() throws IOException;
809 int pos = bufferPos;
810
811 // hand-inlined ensureAvailable(8);
812 if (bufferSize - pos < 8) {
813 refillBuffer(8);
814 pos = bufferPos;
815 }
816
817 final byte[] buffer = this.buffer;
818 bufferPos = pos + 8;
819 return ((((long) buffer[pos] & 0xffL)) |
820 (((long) buffer[pos + 1] & 0xffL) << 8) |
821 (((long) buffer[pos + 2] & 0xffL) << 16) |
822 (((long) buffer[pos + 3] & 0xffL) << 24) |
823 (((long) buffer[pos + 4] & 0xffL) << 32) |
824 (((long) buffer[pos + 5] & 0xffL) << 40) |
825 (((long) buffer[pos + 6] & 0xffL) << 48) |
826 (((long) buffer[pos + 7] & 0xffL) << 56));
827 }
828
829 /**
830 * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers
831 * into values that can be efficiently encoded with varint. (Otherwise,
832 * negative values must be sign-extended to 64 bits to be varint encoded,
833 * thus always taking 10 bytes on the wire.)
834 *
835 * @param n An unsigned 32-bit integer, stored in a signed int because
836 * Java has no explicit unsigned support.
837 * @return A signed 32-bit integer.
838 */
839 public static int decodeZigZag32(final int n) {
840 return (n >>> 1) ^ -(n & 1);
841 }
842
843 /**
844 * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers
845 * into values that can be efficiently encoded with varint. (Otherwise,
846 * negative values must be sign-extended to 64 bits to be varint encoded,
847 * thus always taking 10 bytes on the wire.)
848 *
849 * @param n An unsigned 64-bit integer, stored in a signed int because
850 * Java has no explicit unsigned support.
851 * @return A signed 64-bit integer.
852 */
853 public static long decodeZigZag64(final long n) {
854 return (n >>> 1) ^ -(n & 1);
855 }
856 327
857 // ----------------------------------------------------------------- 328 // -----------------------------------------------------------------
858 329
859 private final byte[] buffer; 330 /**
860 private final boolean bufferIsImmutable; 331 * Enables {@link ByteString} aliasing of the underlying buffer, trading off o n buffer pinning for
861 private int bufferSize; 332 * data copies. Only valid for buffer-backed streams.
862 private int bufferSizeAfterLimit; 333 */
863 private int bufferPos; 334 public abstract void enableAliasing(boolean enabled);
864 private final InputStream input; 335
865 private int lastTag; 336 /**
866 private boolean enableAliasing = false; 337 * Set the maximum message recursion depth. In order to prevent malicious mess ages from causing
867 338 * stack overflows, {@code CodedInputStream} limits how deeply messages may be nested. The default
868 /** 339 * limit is 64.
869 * The total number of bytes read before the current buffer. The total
870 * bytes read up to the current position can be computed as
871 * {@code totalBytesRetired + bufferPos}. This value may be negative if
872 * reading started in the middle of the current buffer (e.g. if the
873 * constructor that takes a byte array and an offset was used).
874 */
875 private int totalBytesRetired;
876
877 /** The absolute position of the end of the current message. */
878 private int currentLimit = Integer.MAX_VALUE;
879
880 /** See setRecursionLimit() */
881 private int recursionDepth;
882 private int recursionLimit = DEFAULT_RECURSION_LIMIT;
883
884 /** See setSizeLimit() */
885 private int sizeLimit = DEFAULT_SIZE_LIMIT;
886
887 private static final int DEFAULT_RECURSION_LIMIT = 100;
888 private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB
889 private static final int BUFFER_SIZE = 4096;
890
891 private CodedInputStream(
892 final byte[] buffer, final int off, final int len, boolean bufferIsImmutab le) {
893 this.buffer = buffer;
894 bufferSize = off + len;
895 bufferPos = off;
896 totalBytesRetired = -off;
897 input = null;
898 this.bufferIsImmutable = bufferIsImmutable;
899 }
900
901 private CodedInputStream(final InputStream input, int bufferSize) {
902 buffer = new byte[bufferSize];
903 bufferSize = 0;
904 bufferPos = 0;
905 totalBytesRetired = 0;
906 this.input = input;
907 bufferIsImmutable = false;
908 }
909
910 public void enableAliasing(boolean enabled) {
911 this.enableAliasing = enabled;
912 }
913
914 /**
915 * Set the maximum message recursion depth. In order to prevent malicious
916 * messages from causing stack overflows, {@code CodedInputStream} limits
917 * how deeply messages may be nested. The default limit is 64.
918 * 340 *
919 * @return the old limit. 341 * @return the old limit.
920 */ 342 */
921 public int setRecursionLimit(final int limit) { 343 public final int setRecursionLimit(final int limit) {
922 if (limit < 0) { 344 if (limit < 0) {
923 throw new IllegalArgumentException( 345 throw new IllegalArgumentException("Recursion limit cannot be negative: " + limit);
924 "Recursion limit cannot be negative: " + limit);
925 } 346 }
926 final int oldLimit = recursionLimit; 347 final int oldLimit = recursionLimit;
927 recursionLimit = limit; 348 recursionLimit = limit;
928 return oldLimit; 349 return oldLimit;
929 } 350 }
930 351
931 /** 352 /**
932 * Set the maximum message size. In order to prevent malicious 353 * Only valid for {@link InputStream}-backed streams.
933 * messages from exhausting memory or causing integer overflows, 354 *
934 * {@code CodedInputStream} limits how large a message may be. 355 * <p>Set the maximum message size. In order to prevent malicious messages fro m exhausting memory
935 * The default limit is 64MB. You should set this limit as small 356 * or causing integer overflows, {@code CodedInputStream} limits how large a m essage may be. The
936 * as you can without harming your app's functionality. Note that 357 * default limit is 64MB. You should set this limit as small as you can withou t harming your app's
937 * size limits only apply when reading from an {@code InputStream}, not 358 * functionality. Note that size limits only apply when reading from an {@code InputStream}, not
938 * when constructed around a raw byte array (nor with 359 * when constructed around a raw byte array (nor with {@link ByteString#newCod edInput}).
939 * {@link ByteString#newCodedInput}). 360 *
940 * <p> 361 * <p>If you want to read several messages from a single CodedInputStream, you could call {@link
941 * If you want to read several messages from a single CodedInputStream, you 362 * #resetSizeCounter()} after each one to avoid hitting the size limit.
942 * could call {@link #resetSizeCounter()} after each one to avoid hitting the
943 * size limit.
944 * 363 *
945 * @return the old limit. 364 * @return the old limit.
946 */ 365 */
947 public int setSizeLimit(final int limit) { 366 public final int setSizeLimit(final int limit) {
948 if (limit < 0) { 367 if (limit < 0) {
949 throw new IllegalArgumentException( 368 throw new IllegalArgumentException("Size limit cannot be negative: " + lim it);
950 "Size limit cannot be negative: " + limit);
951 } 369 }
952 final int oldLimit = sizeLimit; 370 final int oldLimit = sizeLimit;
953 sizeLimit = limit; 371 sizeLimit = limit;
954 return oldLimit; 372 return oldLimit;
955 } 373 }
956 374
957 /** 375 /**
958 * Resets the current size counter to zero (see {@link #setSizeLimit(int)}). 376 * Resets the current size counter to zero (see {@link #setSizeLimit(int)}). O nly valid for {@link
377 * InputStream}-backed streams.
959 */ 378 */
960 public void resetSizeCounter() { 379 public abstract void resetSizeCounter();
961 totalBytesRetired = -bufferPos;
962 }
963 380
964 /** 381 /**
965 * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This 382 * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This i s called when
966 * is called when descending into a length-delimited embedded message. 383 * descending into a length-delimited embedded message.
967 * 384 *
968 * <p>Note that {@code pushLimit()} does NOT affect how many bytes the 385 * <p>Note that {@code pushLimit()} does NOT affect how many bytes the {@code CodedInputStream}
969 * {@code CodedInputStream} reads from an underlying {@code InputStream} when 386 * reads from an underlying {@code InputStream} when refreshing its buffer. If you need to prevent
970 * refreshing its buffer. If you need to prevent reading past a certain 387 * reading past a certain point in the underlying {@code InputStream} (e.g. be cause you expect it
971 * point in the underlying {@code InputStream} (e.g. because you expect it to 388 * to contain more data after the end of the message which you need to handle differently) then
972 * contain more data after the end of the message which you need to handle 389 * you must place a wrapper around your {@code InputStream} which limits the a mount of data that
973 * differently) then you must place a wrapper around your {@code InputStream} 390 * can be read from it.
974 * which limits the amount of data that can be read from it.
975 * 391 *
976 * @return the old limit. 392 * @return the old limit.
977 */ 393 */
978 public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { 394 public abstract int pushLimit(int byteLimit) throws InvalidProtocolBufferExcep tion;
979 if (byteLimit < 0) {
980 throw InvalidProtocolBufferException.negativeSize();
981 }
982 byteLimit += totalBytesRetired + bufferPos;
983 final int oldLimit = currentLimit;
984 if (byteLimit > oldLimit) {
985 throw InvalidProtocolBufferException.truncatedMessage();
986 }
987 currentLimit = byteLimit;
988
989 recomputeBufferSizeAfterLimit();
990
991 return oldLimit;
992 }
993
994 private void recomputeBufferSizeAfterLimit() {
995 bufferSize += bufferSizeAfterLimit;
996 final int bufferEnd = totalBytesRetired + bufferSize;
997 if (bufferEnd > currentLimit) {
998 // Limit is in current buffer.
999 bufferSizeAfterLimit = bufferEnd - currentLimit;
1000 bufferSize -= bufferSizeAfterLimit;
1001 } else {
1002 bufferSizeAfterLimit = 0;
1003 }
1004 }
1005 395
1006 /** 396 /**
1007 * Discards the current limit, returning to the previous limit. 397 * Discards the current limit, returning to the previous limit.
1008 * 398 *
1009 * @param oldLimit The old limit, as returned by {@code pushLimit}. 399 * @param oldLimit The old limit, as returned by {@code pushLimit}.
1010 */ 400 */
1011 public void popLimit(final int oldLimit) { 401 public abstract void popLimit(final int oldLimit);
1012 currentLimit = oldLimit; 402
1013 recomputeBufferSizeAfterLimit(); 403 /**
404 * Returns the number of bytes to be read before the current limit. If no limi t is set, returns
405 * -1.
406 */
407 public abstract int getBytesUntilLimit();
408
409 /**
410 * Returns true if the stream has reached the end of the input. This is the ca se if either the end
411 * of the underlying input source has been reached or if the stream has reache d a limit created
412 * using {@link #pushLimit(int)}.
413 */
414 public abstract boolean isAtEnd() throws IOException;
415
416 /**
417 * The total bytes read up to the current position. Calling {@link #resetSizeC ounter()} resets
418 * this value to zero.
419 */
420 public abstract int getTotalBytesRead();
421
422 /**
423 * Read one byte from the input.
424 *
425 * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached.
426 */
427 public abstract byte readRawByte() throws IOException;
428
429 /**
430 * Read a fixed size of bytes from the input.
431 *
432 * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached.
433 */
434 public abstract byte[] readRawBytes(final int size) throws IOException;
435
436 /**
437 * Reads and discards {@code size} bytes.
438 *
439 * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached.
440 */
441 public abstract void skipRawBytes(final int size) throws IOException;
442
443 /**
444 * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers into v alues that can be
445 * efficiently encoded with varint. (Otherwise, negative values must be sign-e xtended to 64 bits
446 * to be varint encoded, thus always taking 10 bytes on the wire.)
447 *
448 * @param n An unsigned 32-bit integer, stored in a signed int because Java ha s no explicit
449 * unsigned support.
450 * @return A signed 32-bit integer.
451 */
452 public static int decodeZigZag32(final int n) {
453 return (n >>> 1) ^ -(n & 1);
1014 } 454 }
1015 455
1016 /** 456 /**
1017 * Returns the number of bytes to be read before the current limit. 457 * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers into v alues that can be
1018 * If no limit is set, returns -1. 458 * efficiently encoded with varint. (Otherwise, negative values must be sign-e xtended to 64 bits
459 * to be varint encoded, thus always taking 10 bytes on the wire.)
460 *
461 * @param n An unsigned 64-bit integer, stored in a signed int because Java ha s no explicit
462 * unsigned support.
463 * @return A signed 64-bit integer.
1019 */ 464 */
1020 public int getBytesUntilLimit() { 465 public static long decodeZigZag64(final long n) {
1021 if (currentLimit == Integer.MAX_VALUE) { 466 return (n >>> 1) ^ -(n & 1);
1022 return -1;
1023 }
1024
1025 final int currentAbsolutePosition = totalBytesRetired + bufferPos;
1026 return currentLimit - currentAbsolutePosition;
1027 } 467 }
1028 468
1029 /** 469 /**
1030 * Returns true if the stream has reached the end of the input. This is the 470 * Like {@link #readRawVarint32(InputStream)}, but expects that the caller has already read one
1031 * case if either the end of the underlying input source has been reached or 471 * byte. This allows the caller to determine if EOF has been reached before at tempting to read.
1032 * if the stream has reached a limit created using {@link #pushLimit(int)}.
1033 */ 472 */
1034 public boolean isAtEnd() throws IOException { 473 public static int readRawVarint32(final int firstByte, final InputStream input )
1035 return bufferPos == bufferSize && !tryRefillBuffer(1); 474 throws IOException {
475 if ((firstByte & 0x80) == 0) {
476 return firstByte;
477 }
478
479 int result = firstByte & 0x7f;
480 int offset = 7;
481 for (; offset < 32; offset += 7) {
482 final int b = input.read();
483 if (b == -1) {
484 throw InvalidProtocolBufferException.truncatedMessage();
485 }
486 result |= (b & 0x7f) << offset;
487 if ((b & 0x80) == 0) {
488 return result;
489 }
490 }
491 // Keep reading up to 64 bits.
492 for (; offset < 64; offset += 7) {
493 final int b = input.read();
494 if (b == -1) {
495 throw InvalidProtocolBufferException.truncatedMessage();
496 }
497 if ((b & 0x80) == 0) {
498 return result;
499 }
500 }
501 throw InvalidProtocolBufferException.malformedVarint();
1036 } 502 }
1037 503
1038 /** 504 /**
1039 * The total bytes read up to the current position. Calling 505 * Reads a varint from the input one byte at a time, so that it does not read any bytes after the
1040 * {@link #resetSizeCounter()} resets this value to zero. 506 * end of the varint. If you simply wrapped the stream in a CodedInputStream a nd used {@link
507 * #readRawVarint32(InputStream)} then you would probably end up reading past the end of the
508 * varint since CodedInputStream buffers its input.
1041 */ 509 */
1042 public int getTotalBytesRead() { 510 static int readRawVarint32(final InputStream input) throws IOException {
1043 return totalBytesRetired + bufferPos; 511 final int firstByte = input.read();
512 if (firstByte == -1) {
513 throw InvalidProtocolBufferException.truncatedMessage();
514 }
515 return readRawVarint32(firstByte, input);
1044 } 516 }
1045 517
1046 private interface RefillCallback { 518 /** A {@link CodedInputStream} implementation that uses a backing array as the input. */
1047 void onRefill(); 519 private static final class ArrayDecoder extends CodedInputStream {
520 private final byte[] buffer;
521 private final boolean immutable;
522 private int limit;
523 private int bufferSizeAfterLimit;
524 private int pos;
525 private int startPos;
526 private int lastTag;
527 private boolean enableAliasing;
528
529 /** The absolute position of the end of the current message. */
530 private int currentLimit = Integer.MAX_VALUE;
531
532 private ArrayDecoder(final byte[] buffer, final int offset, final int len, b oolean immutable) {
533 this.buffer = buffer;
534 limit = offset + len;
535 pos = offset;
536 startPos = pos;
537 this.immutable = immutable;
538 }
539
540 @Override
541 public int readTag() throws IOException {
542 if (isAtEnd()) {
543 lastTag = 0;
544 return 0;
545 }
546
547 lastTag = readRawVarint32();
548 if (WireFormat.getTagFieldNumber(lastTag) == 0) {
549 // If we actually read zero (or any tag number corresponding to field
550 // number zero), that's not a valid tag.
551 throw InvalidProtocolBufferException.invalidTag();
552 }
553 return lastTag;
554 }
555
556 @Override
557 public void checkLastTagWas(final int value) throws InvalidProtocolBufferExc eption {
558 if (lastTag != value) {
559 throw InvalidProtocolBufferException.invalidEndTag();
560 }
561 }
562
563 @Override
564 public int getLastTag() {
565 return lastTag;
566 }
567
568 @Override
569 public boolean skipField(final int tag) throws IOException {
570 switch (WireFormat.getTagWireType(tag)) {
571 case WireFormat.WIRETYPE_VARINT:
572 skipRawVarint();
573 return true;
574 case WireFormat.WIRETYPE_FIXED64:
575 skipRawBytes(FIXED_64_SIZE);
576 return true;
577 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
578 skipRawBytes(readRawVarint32());
579 return true;
580 case WireFormat.WIRETYPE_START_GROUP:
581 skipMessage();
582 checkLastTagWas(
583 WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.W IRETYPE_END_GROUP));
584 return true;
585 case WireFormat.WIRETYPE_END_GROUP:
586 return false;
587 case WireFormat.WIRETYPE_FIXED32:
588 skipRawBytes(FIXED_32_SIZE);
589 return true;
590 default:
591 throw InvalidProtocolBufferException.invalidWireType();
592 }
593 }
594
595 @Override
596 public boolean skipField(final int tag, final CodedOutputStream output) thro ws IOException {
597 switch (WireFormat.getTagWireType(tag)) {
598 case WireFormat.WIRETYPE_VARINT:
599 {
600 long value = readInt64();
601 output.writeRawVarint32(tag);
602 output.writeUInt64NoTag(value);
603 return true;
604 }
605 case WireFormat.WIRETYPE_FIXED64:
606 {
607 long value = readRawLittleEndian64();
608 output.writeRawVarint32(tag);
609 output.writeFixed64NoTag(value);
610 return true;
611 }
612 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
613 {
614 ByteString value = readBytes();
615 output.writeRawVarint32(tag);
616 output.writeBytesNoTag(value);
617 return true;
618 }
619 case WireFormat.WIRETYPE_START_GROUP:
620 {
621 output.writeRawVarint32(tag);
622 skipMessage(output);
623 int endtag =
624 WireFormat.makeTag(
625 WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_G ROUP);
626 checkLastTagWas(endtag);
627 output.writeRawVarint32(endtag);
628 return true;
629 }
630 case WireFormat.WIRETYPE_END_GROUP:
631 {
632 return false;
633 }
634 case WireFormat.WIRETYPE_FIXED32:
635 {
636 int value = readRawLittleEndian32();
637 output.writeRawVarint32(tag);
638 output.writeFixed32NoTag(value);
639 return true;
640 }
641 default:
642 throw InvalidProtocolBufferException.invalidWireType();
643 }
644 }
645
646 @Override
647 public void skipMessage() throws IOException {
648 while (true) {
649 final int tag = readTag();
650 if (tag == 0 || !skipField(tag)) {
651 return;
652 }
653 }
654 }
655
656 @Override
657 public void skipMessage(CodedOutputStream output) throws IOException {
658 while (true) {
659 final int tag = readTag();
660 if (tag == 0 || !skipField(tag, output)) {
661 return;
662 }
663 }
664 }
665
666
667 // -----------------------------------------------------------------
668
669 @Override
670 public double readDouble() throws IOException {
671 return Double.longBitsToDouble(readRawLittleEndian64());
672 }
673
674 @Override
675 public float readFloat() throws IOException {
676 return Float.intBitsToFloat(readRawLittleEndian32());
677 }
678
679 @Override
680 public long readUInt64() throws IOException {
681 return readRawVarint64();
682 }
683
684 @Override
685 public long readInt64() throws IOException {
686 return readRawVarint64();
687 }
688
689 @Override
690 public int readInt32() throws IOException {
691 return readRawVarint32();
692 }
693
694 @Override
695 public long readFixed64() throws IOException {
696 return readRawLittleEndian64();
697 }
698
699 @Override
700 public int readFixed32() throws IOException {
701 return readRawLittleEndian32();
702 }
703
704 @Override
705 public boolean readBool() throws IOException {
706 return readRawVarint64() != 0;
707 }
708
709 @Override
710 public String readString() throws IOException {
711 final int size = readRawVarint32();
712 if (size > 0 && size <= (limit - pos)) {
713 // Fast path: We already have the bytes in a contiguous buffer, so
714 // just copy directly from it.
715 final String result = new String(buffer, pos, size, UTF_8);
716 pos += size;
717 return result;
718 }
719
720 if (size == 0) {
721 return "";
722 }
723 if (size < 0) {
724 throw InvalidProtocolBufferException.negativeSize();
725 }
726 throw InvalidProtocolBufferException.truncatedMessage();
727 }
728
729 @Override
730 public String readStringRequireUtf8() throws IOException {
731 final int size = readRawVarint32();
732 if (size > 0 && size <= (limit - pos)) {
733 // TODO(martinrb): We could save a pass by validating while decoding.
734 if (!Utf8.isValidUtf8(buffer, pos, pos + size)) {
735 throw InvalidProtocolBufferException.invalidUtf8();
736 }
737 final int tempPos = pos;
738 pos += size;
739 return new String(buffer, tempPos, size, UTF_8);
740 }
741
742 if (size == 0) {
743 return "";
744 }
745 if (size <= 0) {
746 throw InvalidProtocolBufferException.negativeSize();
747 }
748 throw InvalidProtocolBufferException.truncatedMessage();
749 }
750
751 @Override
752 public void readGroup(
753 final int fieldNumber,
754 final MessageLite.Builder builder,
755 final ExtensionRegistryLite extensionRegistry)
756 throws IOException {
757 if (recursionDepth >= recursionLimit) {
758 throw InvalidProtocolBufferException.recursionLimitExceeded();
759 }
760 ++recursionDepth;
761 builder.mergeFrom(this, extensionRegistry);
762 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GR OUP));
763 --recursionDepth;
764 }
765
766
767 @Override
768 public <T extends MessageLite> T readGroup(
769 final int fieldNumber,
770 final Parser<T> parser,
771 final ExtensionRegistryLite extensionRegistry)
772 throws IOException {
773 if (recursionDepth >= recursionLimit) {
774 throw InvalidProtocolBufferException.recursionLimitExceeded();
775 }
776 ++recursionDepth;
777 T result = parser.parsePartialFrom(this, extensionRegistry);
778 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GR OUP));
779 --recursionDepth;
780 return result;
781 }
782
783 @Deprecated
784 @Override
785 public void readUnknownGroup(final int fieldNumber, final MessageLite.Builde r builder)
786 throws IOException {
787 readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
788 }
789
790 @Override
791 public void readMessage(
792 final MessageLite.Builder builder, final ExtensionRegistryLite extension Registry)
793 throws IOException {
794 final int length = readRawVarint32();
795 if (recursionDepth >= recursionLimit) {
796 throw InvalidProtocolBufferException.recursionLimitExceeded();
797 }
798 final int oldLimit = pushLimit(length);
799 ++recursionDepth;
800 builder.mergeFrom(this, extensionRegistry);
801 checkLastTagWas(0);
802 --recursionDepth;
803 popLimit(oldLimit);
804 }
805
806
807 @Override
808 public <T extends MessageLite> T readMessage(
809 final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) t hrows IOException {
810 int length = readRawVarint32();
811 if (recursionDepth >= recursionLimit) {
812 throw InvalidProtocolBufferException.recursionLimitExceeded();
813 }
814 final int oldLimit = pushLimit(length);
815 ++recursionDepth;
816 T result = parser.parsePartialFrom(this, extensionRegistry);
817 checkLastTagWas(0);
818 --recursionDepth;
819 popLimit(oldLimit);
820 return result;
821 }
822
823 @Override
824 public ByteString readBytes() throws IOException {
825 final int size = readRawVarint32();
826 if (size > 0 && size <= (limit - pos)) {
827 // Fast path: We already have the bytes in a contiguous buffer, so
828 // just copy directly from it.
829 final ByteString result =
830 immutable && enableAliasing
831 ? ByteString.wrap(buffer, pos, size)
832 : ByteString.copyFrom(buffer, pos, size);
833 pos += size;
834 return result;
835 }
836 if (size == 0) {
837 return ByteString.EMPTY;
838 }
839 // Slow path: Build a byte array first then copy it.
840 return ByteString.wrap(readRawBytes(size));
841 }
842
843 @Override
844 public byte[] readByteArray() throws IOException {
845 final int size = readRawVarint32();
846 return readRawBytes(size);
847 }
848
849 @Override
850 public ByteBuffer readByteBuffer() throws IOException {
851 final int size = readRawVarint32();
852 if (size > 0 && size <= (limit - pos)) {
853 // Fast path: We already have the bytes in a contiguous buffer.
854 // When aliasing is enabled, we can return a ByteBuffer pointing directl y
855 // into the underlying byte array without copy if the CodedInputStream i s
856 // constructed from a byte array. If aliasing is disabled or the input i s
857 // from an InputStream or ByteString, we have to make a copy of the byte s.
858 ByteBuffer result =
859 !immutable && enableAliasing
860 ? ByteBuffer.wrap(buffer, pos, size).slice()
861 : ByteBuffer.wrap(Arrays.copyOfRange(buffer, pos, pos + size));
862 pos += size;
863 // TODO(nathanmittler): Investigate making the ByteBuffer be made read-o nly
864 return result;
865 }
866
867 if (size == 0) {
868 return EMPTY_BYTE_BUFFER;
869 }
870 if (size < 0) {
871 throw InvalidProtocolBufferException.negativeSize();
872 }
873 throw InvalidProtocolBufferException.truncatedMessage();
874 }
875
876 @Override
877 public int readUInt32() throws IOException {
878 return readRawVarint32();
879 }
880
881 @Override
882 public int readEnum() throws IOException {
883 return readRawVarint32();
884 }
885
886 @Override
887 public int readSFixed32() throws IOException {
888 return readRawLittleEndian32();
889 }
890
891 @Override
892 public long readSFixed64() throws IOException {
893 return readRawLittleEndian64();
894 }
895
896 @Override
897 public int readSInt32() throws IOException {
898 return decodeZigZag32(readRawVarint32());
899 }
900
901 @Override
902 public long readSInt64() throws IOException {
903 return decodeZigZag64(readRawVarint64());
904 }
905
906 // =================================================================
907
908 @Override
909 public int readRawVarint32() throws IOException {
910 // See implementation notes for readRawVarint64
911 fastpath:
912 {
913 int tempPos = pos;
914
915 if (limit == tempPos) {
916 break fastpath;
917 }
918
919 final byte[] buffer = this.buffer;
920 int x;
921 if ((x = buffer[tempPos++]) >= 0) {
922 pos = tempPos;
923 return x;
924 } else if (limit - tempPos < 9) {
925 break fastpath;
926 } else if ((x ^= (buffer[tempPos++] << 7)) < 0) {
927 x ^= (~0 << 7);
928 } else if ((x ^= (buffer[tempPos++] << 14)) >= 0) {
929 x ^= (~0 << 7) ^ (~0 << 14);
930 } else if ((x ^= (buffer[tempPos++] << 21)) < 0) {
931 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
932 } else {
933 int y = buffer[tempPos++];
934 x ^= y << 28;
935 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
936 if (y < 0
937 && buffer[tempPos++] < 0
938 && buffer[tempPos++] < 0
939 && buffer[tempPos++] < 0
940 && buffer[tempPos++] < 0
941 && buffer[tempPos++] < 0) {
942 break fastpath; // Will throw malformedVarint()
943 }
944 }
945 pos = tempPos;
946 return x;
947 }
948 return (int) readRawVarint64SlowPath();
949 }
950
951 private void skipRawVarint() throws IOException {
952 if (limit - pos >= MAX_VARINT_SIZE) {
953 skipRawVarintFastPath();
954 } else {
955 skipRawVarintSlowPath();
956 }
957 }
958
959 private void skipRawVarintFastPath() throws IOException {
960 for (int i = 0; i < MAX_VARINT_SIZE; i++) {
961 if (buffer[pos++] >= 0) {
962 return;
963 }
964 }
965 throw InvalidProtocolBufferException.malformedVarint();
966 }
967
968 private void skipRawVarintSlowPath() throws IOException {
969 for (int i = 0; i < MAX_VARINT_SIZE; i++) {
970 if (readRawByte() >= 0) {
971 return;
972 }
973 }
974 throw InvalidProtocolBufferException.malformedVarint();
975 }
976
977 @Override
978 public long readRawVarint64() throws IOException {
979 // Implementation notes:
980 //
981 // Optimized for one-byte values, expected to be common.
982 // The particular code below was selected from various candidates
983 // empirically, by winning VarintBenchmark.
984 //
985 // Sign extension of (signed) Java bytes is usually a nuisance, but
986 // we exploit it here to more easily obtain the sign of bytes read.
987 // Instead of cleaning up the sign extension bits by masking eagerly,
988 // we delay until we find the final (positive) byte, when we clear all
989 // accumulated bits with one xor. We depend on javac to constant fold.
990 fastpath:
991 {
992 int tempPos = pos;
993
994 if (limit == tempPos) {
995 break fastpath;
996 }
997
998 final byte[] buffer = this.buffer;
999 long x;
1000 int y;
1001 if ((y = buffer[tempPos++]) >= 0) {
1002 pos = tempPos;
1003 return y;
1004 } else if (limit - tempPos < 9) {
1005 break fastpath;
1006 } else if ((y ^= (buffer[tempPos++] << 7)) < 0) {
1007 x = y ^ (~0 << 7);
1008 } else if ((y ^= (buffer[tempPos++] << 14)) >= 0) {
1009 x = y ^ ((~0 << 7) ^ (~0 << 14));
1010 } else if ((y ^= (buffer[tempPos++] << 21)) < 0) {
1011 x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
1012 } else if ((x = y ^ ((long) buffer[tempPos++] << 28)) >= 0L) {
1013 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
1014 } else if ((x ^= ((long) buffer[tempPos++] << 35)) < 0L) {
1015 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35 );
1016 } else if ((x ^= ((long) buffer[tempPos++] << 42)) >= 0L) {
1017 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35 ) ^ (~0L << 42);
1018 } else if ((x ^= ((long) buffer[tempPos++] << 49)) < 0L) {
1019 x ^=
1020 (~0L << 7)
1021 ^ (~0L << 14)
1022 ^ (~0L << 21)
1023 ^ (~0L << 28)
1024 ^ (~0L << 35)
1025 ^ (~0L << 42)
1026 ^ (~0L << 49);
1027 } else {
1028 x ^= ((long) buffer[tempPos++] << 56);
1029 x ^=
1030 (~0L << 7)
1031 ^ (~0L << 14)
1032 ^ (~0L << 21)
1033 ^ (~0L << 28)
1034 ^ (~0L << 35)
1035 ^ (~0L << 42)
1036 ^ (~0L << 49)
1037 ^ (~0L << 56);
1038 if (x < 0L) {
1039 if (buffer[tempPos++] < 0L) {
1040 break fastpath; // Will throw malformedVarint()
1041 }
1042 }
1043 }
1044 pos = tempPos;
1045 return x;
1046 }
1047 return readRawVarint64SlowPath();
1048 }
1049
1050 @Override
1051 long readRawVarint64SlowPath() throws IOException {
1052 long result = 0;
1053 for (int shift = 0; shift < 64; shift += 7) {
1054 final byte b = readRawByte();
1055 result |= (long) (b & 0x7F) << shift;
1056 if ((b & 0x80) == 0) {
1057 return result;
1058 }
1059 }
1060 throw InvalidProtocolBufferException.malformedVarint();
1061 }
1062
1063 @Override
1064 public int readRawLittleEndian32() throws IOException {
1065 int tempPos = pos;
1066
1067 if (limit - tempPos < FIXED_32_SIZE) {
1068 throw InvalidProtocolBufferException.truncatedMessage();
1069 }
1070
1071 final byte[] buffer = this.buffer;
1072 pos = tempPos + FIXED_32_SIZE;
1073 return (((buffer[tempPos] & 0xff))
1074 | ((buffer[tempPos + 1] & 0xff) << 8)
1075 | ((buffer[tempPos + 2] & 0xff) << 16)
1076 | ((buffer[tempPos + 3] & 0xff) << 24));
1077 }
1078
1079 @Override
1080 public long readRawLittleEndian64() throws IOException {
1081 int tempPos = pos;
1082
1083 if (limit - tempPos < FIXED_64_SIZE) {
1084 throw InvalidProtocolBufferException.truncatedMessage();
1085 }
1086
1087 final byte[] buffer = this.buffer;
1088 pos = tempPos + FIXED_64_SIZE;
1089 return (((buffer[tempPos] & 0xffL))
1090 | ((buffer[tempPos + 1] & 0xffL) << 8)
1091 | ((buffer[tempPos + 2] & 0xffL) << 16)
1092 | ((buffer[tempPos + 3] & 0xffL) << 24)
1093 | ((buffer[tempPos + 4] & 0xffL) << 32)
1094 | ((buffer[tempPos + 5] & 0xffL) << 40)
1095 | ((buffer[tempPos + 6] & 0xffL) << 48)
1096 | ((buffer[tempPos + 7] & 0xffL) << 56));
1097 }
1098
1099 @Override
1100 public void enableAliasing(boolean enabled) {
1101 this.enableAliasing = enabled;
1102 }
1103
1104 @Override
1105 public void resetSizeCounter() {
1106 startPos = pos;
1107 }
1108
1109 @Override
1110 public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
1111 if (byteLimit < 0) {
1112 throw InvalidProtocolBufferException.negativeSize();
1113 }
1114 byteLimit += getTotalBytesRead();
1115 final int oldLimit = currentLimit;
1116 if (byteLimit > oldLimit) {
1117 throw InvalidProtocolBufferException.truncatedMessage();
1118 }
1119 currentLimit = byteLimit;
1120
1121 recomputeBufferSizeAfterLimit();
1122
1123 return oldLimit;
1124 }
1125
1126 private void recomputeBufferSizeAfterLimit() {
1127 limit += bufferSizeAfterLimit;
1128 final int bufferEnd = limit - startPos;
1129 if (bufferEnd > currentLimit) {
1130 // Limit is in current buffer.
1131 bufferSizeAfterLimit = bufferEnd - currentLimit;
1132 limit -= bufferSizeAfterLimit;
1133 } else {
1134 bufferSizeAfterLimit = 0;
1135 }
1136 }
1137
1138 @Override
1139 public void popLimit(final int oldLimit) {
1140 currentLimit = oldLimit;
1141 recomputeBufferSizeAfterLimit();
1142 }
1143
1144 @Override
1145 public int getBytesUntilLimit() {
1146 if (currentLimit == Integer.MAX_VALUE) {
1147 return -1;
1148 }
1149
1150 return currentLimit - getTotalBytesRead();
1151 }
1152
1153 @Override
1154 public boolean isAtEnd() throws IOException {
1155 return pos == limit;
1156 }
1157
1158 @Override
1159 public int getTotalBytesRead() {
1160 return pos - startPos;
1161 }
1162
1163 @Override
1164 public byte readRawByte() throws IOException {
1165 if (pos == limit) {
1166 throw InvalidProtocolBufferException.truncatedMessage();
1167 }
1168 return buffer[pos++];
1169 }
1170
1171 @Override
1172 public byte[] readRawBytes(final int length) throws IOException {
1173 if (length > 0 && length <= (limit - pos)) {
1174 final int tempPos = pos;
1175 pos += length;
1176 return Arrays.copyOfRange(buffer, tempPos, pos);
1177 }
1178
1179 if (length <= 0) {
1180 if (length == 0) {
1181 return Internal.EMPTY_BYTE_ARRAY;
1182 } else {
1183 throw InvalidProtocolBufferException.negativeSize();
1184 }
1185 }
1186 throw InvalidProtocolBufferException.truncatedMessage();
1187 }
1188
1189 @Override
1190 public void skipRawBytes(final int length) throws IOException {
1191 if (length >= 0 && length <= (limit - pos)) {
1192 // We have all the bytes we need already.
1193 pos += length;
1194 return;
1195 }
1196
1197 if (length < 0) {
1198 throw InvalidProtocolBufferException.negativeSize();
1199 }
1200 throw InvalidProtocolBufferException.truncatedMessage();
1201 }
1048 } 1202 }
1049 1203
1050 private RefillCallback refillCallback = null;
1051
1052 /** 1204 /**
1053 * Reads more bytes from the input, making at least {@code n} bytes available 1205 * A {@link CodedInputStream} implementation that uses a backing direct ByteBu ffer as the input.
1054 * in the buffer. Caller must ensure that the requested space is not yet 1206 * Requires the use of {@code sun.misc.Unsafe} to perform fast reads on the bu ffer.
1055 * available, and that the requested space is less than BUFFER_SIZE.
1056 *
1057 * @throws InvalidProtocolBufferException The end of the stream or the current
1058 * limit was reached.
1059 */ 1207 */
1060 private void refillBuffer(int n) throws IOException { 1208 private static final class UnsafeDirectNioDecoder extends CodedInputStream {
1061 if (!tryRefillBuffer(n)) { 1209 /** The direct buffer that is backing this stream. */
1210 private final ByteBuffer buffer;
1211
1212 /**
1213 * If {@code true}, indicates that the buffer is backing a {@link ByteString } and is therefore
1214 * considered to be an immutable input source.
1215 */
1216 private final boolean immutable;
1217
1218 /** The unsafe address of the content of {@link #buffer}. */
1219 private final long address;
1220
1221 /** The unsafe address of the current read limit of the buffer. */
1222 private long limit;
1223
1224 /** The unsafe address of the current read position of the buffer. */
1225 private long pos;
1226
1227 /** The unsafe address of the starting read position. */
1228 private long startPos;
1229
1230 /** The amount of available data in the buffer beyond {@link #limit}. */
1231 private int bufferSizeAfterLimit;
1232
1233 /** The last tag that was read from this stream. */
1234 private int lastTag;
1235
1236 /**
1237 * If {@code true}, indicates that calls to read {@link ByteString} or {@cod e byte[]}
1238 * <strong>may</strong> return slices of the underlying buffer, rather than copies.
1239 */
1240 private boolean enableAliasing;
1241
1242 /** The absolute position of the end of the current message. */
1243 private int currentLimit = Integer.MAX_VALUE;
1244
1245 static boolean isSupported() {
1246 return UnsafeUtil.hasUnsafeByteBufferOperations();
1247 }
1248
1249 private UnsafeDirectNioDecoder(ByteBuffer buffer, boolean immutable) {
1250 this.buffer = buffer;
1251 address = UnsafeUtil.addressOffset(buffer);
1252 limit = address + buffer.limit();
1253 pos = address + buffer.position();
1254 startPos = pos;
1255 this.immutable = immutable;
1256 }
1257
1258 @Override
1259 public int readTag() throws IOException {
1260 if (isAtEnd()) {
1261 lastTag = 0;
1262 return 0;
1263 }
1264
1265 lastTag = readRawVarint32();
1266 if (WireFormat.getTagFieldNumber(lastTag) == 0) {
1267 // If we actually read zero (or any tag number corresponding to field
1268 // number zero), that's not a valid tag.
1269 throw InvalidProtocolBufferException.invalidTag();
1270 }
1271 return lastTag;
1272 }
1273
1274 @Override
1275 public void checkLastTagWas(final int value) throws InvalidProtocolBufferExc eption {
1276 if (lastTag != value) {
1277 throw InvalidProtocolBufferException.invalidEndTag();
1278 }
1279 }
1280
1281 @Override
1282 public int getLastTag() {
1283 return lastTag;
1284 }
1285
1286 @Override
1287 public boolean skipField(final int tag) throws IOException {
1288 switch (WireFormat.getTagWireType(tag)) {
1289 case WireFormat.WIRETYPE_VARINT:
1290 skipRawVarint();
1291 return true;
1292 case WireFormat.WIRETYPE_FIXED64:
1293 skipRawBytes(FIXED_64_SIZE);
1294 return true;
1295 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
1296 skipRawBytes(readRawVarint32());
1297 return true;
1298 case WireFormat.WIRETYPE_START_GROUP:
1299 skipMessage();
1300 checkLastTagWas(
1301 WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.W IRETYPE_END_GROUP));
1302 return true;
1303 case WireFormat.WIRETYPE_END_GROUP:
1304 return false;
1305 case WireFormat.WIRETYPE_FIXED32:
1306 skipRawBytes(FIXED_32_SIZE);
1307 return true;
1308 default:
1309 throw InvalidProtocolBufferException.invalidWireType();
1310 }
1311 }
1312
1313 @Override
1314 public boolean skipField(final int tag, final CodedOutputStream output) thro ws IOException {
1315 switch (WireFormat.getTagWireType(tag)) {
1316 case WireFormat.WIRETYPE_VARINT:
1317 {
1318 long value = readInt64();
1319 output.writeRawVarint32(tag);
1320 output.writeUInt64NoTag(value);
1321 return true;
1322 }
1323 case WireFormat.WIRETYPE_FIXED64:
1324 {
1325 long value = readRawLittleEndian64();
1326 output.writeRawVarint32(tag);
1327 output.writeFixed64NoTag(value);
1328 return true;
1329 }
1330 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
1331 {
1332 ByteString value = readBytes();
1333 output.writeRawVarint32(tag);
1334 output.writeBytesNoTag(value);
1335 return true;
1336 }
1337 case WireFormat.WIRETYPE_START_GROUP:
1338 {
1339 output.writeRawVarint32(tag);
1340 skipMessage(output);
1341 int endtag =
1342 WireFormat.makeTag(
1343 WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_G ROUP);
1344 checkLastTagWas(endtag);
1345 output.writeRawVarint32(endtag);
1346 return true;
1347 }
1348 case WireFormat.WIRETYPE_END_GROUP:
1349 {
1350 return false;
1351 }
1352 case WireFormat.WIRETYPE_FIXED32:
1353 {
1354 int value = readRawLittleEndian32();
1355 output.writeRawVarint32(tag);
1356 output.writeFixed32NoTag(value);
1357 return true;
1358 }
1359 default:
1360 throw InvalidProtocolBufferException.invalidWireType();
1361 }
1362 }
1363
1364 @Override
1365 public void skipMessage() throws IOException {
1366 while (true) {
1367 final int tag = readTag();
1368 if (tag == 0 || !skipField(tag)) {
1369 return;
1370 }
1371 }
1372 }
1373
1374 @Override
1375 public void skipMessage(CodedOutputStream output) throws IOException {
1376 while (true) {
1377 final int tag = readTag();
1378 if (tag == 0 || !skipField(tag, output)) {
1379 return;
1380 }
1381 }
1382 }
1383
1384
1385 // -----------------------------------------------------------------
1386
1387 @Override
1388 public double readDouble() throws IOException {
1389 return Double.longBitsToDouble(readRawLittleEndian64());
1390 }
1391
1392 @Override
1393 public float readFloat() throws IOException {
1394 return Float.intBitsToFloat(readRawLittleEndian32());
1395 }
1396
1397 @Override
1398 public long readUInt64() throws IOException {
1399 return readRawVarint64();
1400 }
1401
1402 @Override
1403 public long readInt64() throws IOException {
1404 return readRawVarint64();
1405 }
1406
1407 @Override
1408 public int readInt32() throws IOException {
1409 return readRawVarint32();
1410 }
1411
1412 @Override
1413 public long readFixed64() throws IOException {
1414 return readRawLittleEndian64();
1415 }
1416
1417 @Override
1418 public int readFixed32() throws IOException {
1419 return readRawLittleEndian32();
1420 }
1421
1422 @Override
1423 public boolean readBool() throws IOException {
1424 return readRawVarint64() != 0;
1425 }
1426
1427 @Override
1428 public String readString() throws IOException {
1429 final int size = readRawVarint32();
1430 if (size > 0 && size <= remaining()) {
1431 // TODO(nathanmittler): Is there a way to avoid this copy?
1432 byte[] bytes = copyToArray(pos, pos + size);
1433 String result = new String(bytes, UTF_8);
1434 pos += size;
1435 return result;
1436 }
1437
1438 if (size == 0) {
1439 return "";
1440 }
1441 if (size < 0) {
1442 throw InvalidProtocolBufferException.negativeSize();
1443 }
1062 throw InvalidProtocolBufferException.truncatedMessage(); 1444 throw InvalidProtocolBufferException.truncatedMessage();
1063 } 1445 }
1446
1447 @Override
1448 public String readStringRequireUtf8() throws IOException {
1449 final int size = readRawVarint32();
1450 if (size >= 0 && size <= remaining()) {
1451 // TODO(nathanmittler): Is there a way to avoid this copy?
1452 byte[] bytes = copyToArray(pos, pos + size);
1453 // TODO(martinrb): We could save a pass by validating while decoding.
1454 if (!Utf8.isValidUtf8(bytes)) {
1455 throw InvalidProtocolBufferException.invalidUtf8();
1456 }
1457
1458 String result = new String(bytes, UTF_8);
1459 pos += size;
1460 return result;
1461 }
1462
1463 if (size == 0) {
1464 return "";
1465 }
1466 if (size <= 0) {
1467 throw InvalidProtocolBufferException.negativeSize();
1468 }
1469 throw InvalidProtocolBufferException.truncatedMessage();
1470 }
1471
1472 @Override
1473 public void readGroup(
1474 final int fieldNumber,
1475 final MessageLite.Builder builder,
1476 final ExtensionRegistryLite extensionRegistry)
1477 throws IOException {
1478 if (recursionDepth >= recursionLimit) {
1479 throw InvalidProtocolBufferException.recursionLimitExceeded();
1480 }
1481 ++recursionDepth;
1482 builder.mergeFrom(this, extensionRegistry);
1483 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GR OUP));
1484 --recursionDepth;
1485 }
1486
1487
1488 @Override
1489 public <T extends MessageLite> T readGroup(
1490 final int fieldNumber,
1491 final Parser<T> parser,
1492 final ExtensionRegistryLite extensionRegistry)
1493 throws IOException {
1494 if (recursionDepth >= recursionLimit) {
1495 throw InvalidProtocolBufferException.recursionLimitExceeded();
1496 }
1497 ++recursionDepth;
1498 T result = parser.parsePartialFrom(this, extensionRegistry);
1499 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GR OUP));
1500 --recursionDepth;
1501 return result;
1502 }
1503
1504 @Deprecated
1505 @Override
1506 public void readUnknownGroup(final int fieldNumber, final MessageLite.Builde r builder)
1507 throws IOException {
1508 readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
1509 }
1510
1511 @Override
1512 public void readMessage(
1513 final MessageLite.Builder builder, final ExtensionRegistryLite extension Registry)
1514 throws IOException {
1515 final int length = readRawVarint32();
1516 if (recursionDepth >= recursionLimit) {
1517 throw InvalidProtocolBufferException.recursionLimitExceeded();
1518 }
1519 final int oldLimit = pushLimit(length);
1520 ++recursionDepth;
1521 builder.mergeFrom(this, extensionRegistry);
1522 checkLastTagWas(0);
1523 --recursionDepth;
1524 popLimit(oldLimit);
1525 }
1526
1527
1528 @Override
1529 public <T extends MessageLite> T readMessage(
1530 final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) t hrows IOException {
1531 int length = readRawVarint32();
1532 if (recursionDepth >= recursionLimit) {
1533 throw InvalidProtocolBufferException.recursionLimitExceeded();
1534 }
1535 final int oldLimit = pushLimit(length);
1536 ++recursionDepth;
1537 T result = parser.parsePartialFrom(this, extensionRegistry);
1538 checkLastTagWas(0);
1539 --recursionDepth;
1540 popLimit(oldLimit);
1541 return result;
1542 }
1543
1544 @Override
1545 public ByteString readBytes() throws IOException {
1546 final int size = readRawVarint32();
1547 if (size > 0 && size <= remaining()) {
1548 ByteBuffer result;
1549 if (immutable && enableAliasing) {
1550 result = slice(pos, pos + size);
1551 } else {
1552 result = copy(pos, pos + size);
1553 }
1554 pos += size;
1555 return ByteString.wrap(result);
1556 }
1557
1558 if (size == 0) {
1559 return ByteString.EMPTY;
1560 }
1561 if (size < 0) {
1562 throw InvalidProtocolBufferException.negativeSize();
1563 }
1564 throw InvalidProtocolBufferException.truncatedMessage();
1565 }
1566
1567 @Override
1568 public byte[] readByteArray() throws IOException {
1569 return readRawBytes(readRawVarint32());
1570 }
1571
1572 @Override
1573 public ByteBuffer readByteBuffer() throws IOException {
1574 final int size = readRawVarint32();
1575 if (size > 0 && size <= remaining()) {
1576 ByteBuffer result;
1577 // "Immutable" implies that buffer is backing a ByteString.
1578 // Disallow slicing in this case to prevent the caller from modifying th e contents
1579 // of the ByteString.
1580 if (!immutable && enableAliasing) {
1581 result = slice(pos, pos + size);
1582 } else {
1583 result = copy(pos, pos + size);
1584 }
1585 pos += size;
1586 // TODO(nathanmittler): Investigate making the ByteBuffer be made read-o nly
1587 return result;
1588 }
1589
1590 if (size == 0) {
1591 return EMPTY_BYTE_BUFFER;
1592 }
1593 if (size < 0) {
1594 throw InvalidProtocolBufferException.negativeSize();
1595 }
1596 throw InvalidProtocolBufferException.truncatedMessage();
1597 }
1598
1599 @Override
1600 public int readUInt32() throws IOException {
1601 return readRawVarint32();
1602 }
1603
1604 @Override
1605 public int readEnum() throws IOException {
1606 return readRawVarint32();
1607 }
1608
1609 @Override
1610 public int readSFixed32() throws IOException {
1611 return readRawLittleEndian32();
1612 }
1613
1614 @Override
1615 public long readSFixed64() throws IOException {
1616 return readRawLittleEndian64();
1617 }
1618
1619 @Override
1620 public int readSInt32() throws IOException {
1621 return decodeZigZag32(readRawVarint32());
1622 }
1623
1624 @Override
1625 public long readSInt64() throws IOException {
1626 return decodeZigZag64(readRawVarint64());
1627 }
1628
1629 // =================================================================
1630
1631 @Override
1632 public int readRawVarint32() throws IOException {
1633 // See implementation notes for readRawVarint64
1634 fastpath:
1635 {
1636 long tempPos = pos;
1637
1638 if (limit == tempPos) {
1639 break fastpath;
1640 }
1641
1642 int x;
1643 if ((x = UnsafeUtil.getByte(tempPos++)) >= 0) {
1644 pos = tempPos;
1645 return x;
1646 } else if (limit - tempPos < 9) {
1647 break fastpath;
1648 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
1649 x ^= (~0 << 7);
1650 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
1651 x ^= (~0 << 7) ^ (~0 << 14);
1652 } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
1653 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
1654 } else {
1655 int y = UnsafeUtil.getByte(tempPos++);
1656 x ^= y << 28;
1657 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
1658 if (y < 0
1659 && UnsafeUtil.getByte(tempPos++) < 0
1660 && UnsafeUtil.getByte(tempPos++) < 0
1661 && UnsafeUtil.getByte(tempPos++) < 0
1662 && UnsafeUtil.getByte(tempPos++) < 0
1663 && UnsafeUtil.getByte(tempPos++) < 0) {
1664 break fastpath; // Will throw malformedVarint()
1665 }
1666 }
1667 pos = tempPos;
1668 return x;
1669 }
1670 return (int) readRawVarint64SlowPath();
1671 }
1672
1673 private void skipRawVarint() throws IOException {
1674 if (remaining() >= MAX_VARINT_SIZE) {
1675 skipRawVarintFastPath();
1676 } else {
1677 skipRawVarintSlowPath();
1678 }
1679 }
1680
1681 private void skipRawVarintFastPath() throws IOException {
1682 for (int i = 0; i < MAX_VARINT_SIZE; i++) {
1683 if (UnsafeUtil.getByte(pos++) >= 0) {
1684 return;
1685 }
1686 }
1687 throw InvalidProtocolBufferException.malformedVarint();
1688 }
1689
1690 private void skipRawVarintSlowPath() throws IOException {
1691 for (int i = 0; i < MAX_VARINT_SIZE; i++) {
1692 if (readRawByte() >= 0) {
1693 return;
1694 }
1695 }
1696 throw InvalidProtocolBufferException.malformedVarint();
1697 }
1698
1699 @Override
1700 public long readRawVarint64() throws IOException {
1701 // Implementation notes:
1702 //
1703 // Optimized for one-byte values, expected to be common.
1704 // The particular code below was selected from various candidates
1705 // empirically, by winning VarintBenchmark.
1706 //
1707 // Sign extension of (signed) Java bytes is usually a nuisance, but
1708 // we exploit it here to more easily obtain the sign of bytes read.
1709 // Instead of cleaning up the sign extension bits by masking eagerly,
1710 // we delay until we find the final (positive) byte, when we clear all
1711 // accumulated bits with one xor. We depend on javac to constant fold.
1712 fastpath:
1713 {
1714 long tempPos = pos;
1715
1716 if (limit == tempPos) {
1717 break fastpath;
1718 }
1719
1720 long x;
1721 int y;
1722 if ((y = UnsafeUtil.getByte(tempPos++)) >= 0) {
1723 pos = tempPos;
1724 return y;
1725 } else if (limit - tempPos < 9) {
1726 break fastpath;
1727 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
1728 x = y ^ (~0 << 7);
1729 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
1730 x = y ^ ((~0 << 7) ^ (~0 << 14));
1731 } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
1732 x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
1733 } else if ((x = y ^ ((long) UnsafeUtil.getByte(tempPos++) << 28)) >= 0L) {
1734 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
1735 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 35)) < 0L) {
1736 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35 );
1737 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 42)) >= 0L) {
1738 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35 ) ^ (~0L << 42);
1739 } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 49)) < 0L) {
1740 x ^=
1741 (~0L << 7)
1742 ^ (~0L << 14)
1743 ^ (~0L << 21)
1744 ^ (~0L << 28)
1745 ^ (~0L << 35)
1746 ^ (~0L << 42)
1747 ^ (~0L << 49);
1748 } else {
1749 x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56);
1750 x ^=
1751 (~0L << 7)
1752 ^ (~0L << 14)
1753 ^ (~0L << 21)
1754 ^ (~0L << 28)
1755 ^ (~0L << 35)
1756 ^ (~0L << 42)
1757 ^ (~0L << 49)
1758 ^ (~0L << 56);
1759 if (x < 0L) {
1760 if (UnsafeUtil.getByte(tempPos++) < 0L) {
1761 break fastpath; // Will throw malformedVarint()
1762 }
1763 }
1764 }
1765 pos = tempPos;
1766 return x;
1767 }
1768 return readRawVarint64SlowPath();
1769 }
1770
1771 @Override
1772 long readRawVarint64SlowPath() throws IOException {
1773 long result = 0;
1774 for (int shift = 0; shift < 64; shift += 7) {
1775 final byte b = readRawByte();
1776 result |= (long) (b & 0x7F) << shift;
1777 if ((b & 0x80) == 0) {
1778 return result;
1779 }
1780 }
1781 throw InvalidProtocolBufferException.malformedVarint();
1782 }
1783
1784 @Override
1785 public int readRawLittleEndian32() throws IOException {
1786 long tempPos = pos;
1787
1788 if (limit - tempPos < FIXED_32_SIZE) {
1789 throw InvalidProtocolBufferException.truncatedMessage();
1790 }
1791
1792 pos = tempPos + FIXED_32_SIZE;
1793 return (((UnsafeUtil.getByte(tempPos) & 0xff))
1794 | ((UnsafeUtil.getByte(tempPos + 1) & 0xff) << 8)
1795 | ((UnsafeUtil.getByte(tempPos + 2) & 0xff) << 16)
1796 | ((UnsafeUtil.getByte(tempPos + 3) & 0xff) << 24));
1797 }
1798
1799 @Override
1800 public long readRawLittleEndian64() throws IOException {
1801 long tempPos = pos;
1802
1803 if (limit - tempPos < FIXED_64_SIZE) {
1804 throw InvalidProtocolBufferException.truncatedMessage();
1805 }
1806
1807 pos = tempPos + FIXED_64_SIZE;
1808 return (((UnsafeUtil.getByte(tempPos) & 0xffL))
1809 | ((UnsafeUtil.getByte(tempPos + 1) & 0xffL) << 8)
1810 | ((UnsafeUtil.getByte(tempPos + 2) & 0xffL) << 16)
1811 | ((UnsafeUtil.getByte(tempPos + 3) & 0xffL) << 24)
1812 | ((UnsafeUtil.getByte(tempPos + 4) & 0xffL) << 32)
1813 | ((UnsafeUtil.getByte(tempPos + 5) & 0xffL) << 40)
1814 | ((UnsafeUtil.getByte(tempPos + 6) & 0xffL) << 48)
1815 | ((UnsafeUtil.getByte(tempPos + 7) & 0xffL) << 56));
1816 }
1817
1818 @Override
1819 public void enableAliasing(boolean enabled) {
1820 this.enableAliasing = enabled;
1821 }
1822
1823 @Override
1824 public void resetSizeCounter() {
1825 startPos = pos;
1826 }
1827
1828 @Override
1829 public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
1830 if (byteLimit < 0) {
1831 throw InvalidProtocolBufferException.negativeSize();
1832 }
1833 byteLimit += getTotalBytesRead();
1834 final int oldLimit = currentLimit;
1835 if (byteLimit > oldLimit) {
1836 throw InvalidProtocolBufferException.truncatedMessage();
1837 }
1838 currentLimit = byteLimit;
1839
1840 recomputeBufferSizeAfterLimit();
1841
1842 return oldLimit;
1843 }
1844
1845 @Override
1846 public void popLimit(final int oldLimit) {
1847 currentLimit = oldLimit;
1848 recomputeBufferSizeAfterLimit();
1849 }
1850
1851 @Override
1852 public int getBytesUntilLimit() {
1853 if (currentLimit == Integer.MAX_VALUE) {
1854 return -1;
1855 }
1856
1857 return currentLimit - getTotalBytesRead();
1858 }
1859
1860 @Override
1861 public boolean isAtEnd() throws IOException {
1862 return pos == limit;
1863 }
1864
1865 @Override
1866 public int getTotalBytesRead() {
1867 return (int) (pos - startPos);
1868 }
1869
1870 @Override
1871 public byte readRawByte() throws IOException {
1872 if (pos == limit) {
1873 throw InvalidProtocolBufferException.truncatedMessage();
1874 }
1875 return UnsafeUtil.getByte(pos++);
1876 }
1877
1878 @Override
1879 public byte[] readRawBytes(final int length) throws IOException {
1880 if (length >= 0 && length <= remaining()) {
1881 byte[] bytes = new byte[length];
1882 slice(pos, pos + length).get(bytes);
1883 pos += length;
1884 return bytes;
1885 }
1886
1887 if (length <= 0) {
1888 if (length == 0) {
1889 return EMPTY_BYTE_ARRAY;
1890 } else {
1891 throw InvalidProtocolBufferException.negativeSize();
1892 }
1893 }
1894
1895 throw InvalidProtocolBufferException.truncatedMessage();
1896 }
1897
1898 @Override
1899 public void skipRawBytes(final int length) throws IOException {
1900 if (length >= 0 && length <= remaining()) {
1901 // We have all the bytes we need already.
1902 pos += length;
1903 return;
1904 }
1905
1906 if (length < 0) {
1907 throw InvalidProtocolBufferException.negativeSize();
1908 }
1909 throw InvalidProtocolBufferException.truncatedMessage();
1910 }
1911
1912 private void recomputeBufferSizeAfterLimit() {
1913 limit += bufferSizeAfterLimit;
1914 final int bufferEnd = (int) (limit - startPos);
1915 if (bufferEnd > currentLimit) {
1916 // Limit is in current buffer.
1917 bufferSizeAfterLimit = bufferEnd - currentLimit;
1918 limit -= bufferSizeAfterLimit;
1919 } else {
1920 bufferSizeAfterLimit = 0;
1921 }
1922 }
1923
1924 private int remaining() {
1925 return (int) (limit - pos);
1926 }
1927
1928 private int bufferPos(long pos) {
1929 return (int) (pos - address);
1930 }
1931
1932 private ByteBuffer slice(long begin, long end) throws IOException {
1933 int prevPos = buffer.position();
1934 int prevLimit = buffer.limit();
1935 try {
1936 buffer.position(bufferPos(begin));
1937 buffer.limit(bufferPos(end));
1938 return buffer.slice();
1939 } catch (IllegalArgumentException e) {
1940 throw InvalidProtocolBufferException.truncatedMessage();
1941 } finally {
1942 buffer.position(prevPos);
1943 buffer.limit(prevLimit);
1944 }
1945 }
1946
1947 private ByteBuffer copy(long begin, long end) throws IOException {
1948 return ByteBuffer.wrap(copyToArray(begin, end));
1949 }
1950
1951 private byte[] copyToArray(long begin, long end) throws IOException {
1952 int prevPos = buffer.position();
1953 int prevLimit = buffer.limit();
1954 try {
1955 buffer.position(bufferPos(begin));
1956 buffer.limit(bufferPos(end));
1957 byte[] bytes = new byte[(int) (end - begin)];
1958 buffer.get(bytes);
1959 return bytes;
1960 } catch (IllegalArgumentException e) {
1961 throw InvalidProtocolBufferException.truncatedMessage();
1962 } finally {
1963 buffer.position(prevPos);
1964 buffer.limit(prevLimit);
1965 }
1966 }
1064 } 1967 }
1065 1968
1066 /** 1969 /**
1067 * Tries to read more bytes from the input, making at least {@code n} bytes 1970 * Implementation of {@link CodedInputStream} that uses an {@link InputStream} as the data source.
1068 * available in the buffer. Caller must ensure that the requested space is
1069 * not yet available, and that the requested space is less than BUFFER_SIZE.
1070 *
1071 * @return {@code true} if the bytes could be made available; {@code false}
1072 * if the end of the stream or the current limit was reached.
1073 */ 1971 */
1074 private boolean tryRefillBuffer(int n) throws IOException { 1972 private static final class StreamDecoder extends CodedInputStream {
1075 if (bufferPos + n <= bufferSize) { 1973 private final InputStream input;
1076 throw new IllegalStateException( 1974 private final byte[] buffer;
1077 "refillBuffer() called when " + n + 1975 /** bufferSize represents how many bytes are currently filled in the buffer */
1078 " bytes were already available in buffer"); 1976 private int bufferSize;
1079 } 1977
1080 1978 private int bufferSizeAfterLimit;
1081 if (totalBytesRetired + bufferPos + n > currentLimit) { 1979 private int pos;
1082 // Oops, we hit a limit. 1980 private int lastTag;
1083 return false; 1981
1084 } 1982 /**
1085 1983 * The total number of bytes read before the current buffer. The total bytes read up to the
1086 if (refillCallback != null) { 1984 * current position can be computed as {@code totalBytesRetired + pos}. This value may be
1087 refillCallback.onRefill(); 1985 * negative if reading started in the middle of the current buffer (e.g. if the constructor that
1088 } 1986 * takes a byte array and an offset was used).
1089 1987 */
1090 if (input != null) { 1988 private int totalBytesRetired;
1091 int pos = bufferPos; 1989
1092 if (pos > 0) { 1990 /** The absolute position of the end of the current message. */
1093 if (bufferSize > pos) { 1991 private int currentLimit = Integer.MAX_VALUE;
1094 System.arraycopy(buffer, pos, buffer, 0, bufferSize - pos); 1992
1095 } 1993 private StreamDecoder(final InputStream input, int bufferSize) {
1096 totalBytesRetired += pos; 1994 checkNotNull(input, "input");
1097 bufferSize -= pos; 1995 this.input = input;
1098 bufferPos = 0; 1996 this.buffer = new byte[bufferSize];
1997 this.bufferSize = 0;
1998 pos = 0;
1999 totalBytesRetired = 0;
2000 }
2001
2002 @Override
2003 public int readTag() throws IOException {
2004 if (isAtEnd()) {
2005 lastTag = 0;
2006 return 0;
2007 }
2008
2009 lastTag = readRawVarint32();
2010 if (WireFormat.getTagFieldNumber(lastTag) == 0) {
2011 // If we actually read zero (or any tag number corresponding to field
2012 // number zero), that's not a valid tag.
2013 throw InvalidProtocolBufferException.invalidTag();
2014 }
2015 return lastTag;
2016 }
2017
2018 @Override
2019 public void checkLastTagWas(final int value) throws InvalidProtocolBufferExc eption {
2020 if (lastTag != value) {
2021 throw InvalidProtocolBufferException.invalidEndTag();
2022 }
2023 }
2024
2025 @Override
2026 public int getLastTag() {
2027 return lastTag;
2028 }
2029
2030 @Override
2031 public boolean skipField(final int tag) throws IOException {
2032 switch (WireFormat.getTagWireType(tag)) {
2033 case WireFormat.WIRETYPE_VARINT:
2034 skipRawVarint();
2035 return true;
2036 case WireFormat.WIRETYPE_FIXED64:
2037 skipRawBytes(FIXED_64_SIZE);
2038 return true;
2039 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
2040 skipRawBytes(readRawVarint32());
2041 return true;
2042 case WireFormat.WIRETYPE_START_GROUP:
2043 skipMessage();
2044 checkLastTagWas(
2045 WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.W IRETYPE_END_GROUP));
2046 return true;
2047 case WireFormat.WIRETYPE_END_GROUP:
2048 return false;
2049 case WireFormat.WIRETYPE_FIXED32:
2050 skipRawBytes(FIXED_32_SIZE);
2051 return true;
2052 default:
2053 throw InvalidProtocolBufferException.invalidWireType();
2054 }
2055 }
2056
2057 @Override
2058 public boolean skipField(final int tag, final CodedOutputStream output) thro ws IOException {
2059 switch (WireFormat.getTagWireType(tag)) {
2060 case WireFormat.WIRETYPE_VARINT:
2061 {
2062 long value = readInt64();
2063 output.writeRawVarint32(tag);
2064 output.writeUInt64NoTag(value);
2065 return true;
2066 }
2067 case WireFormat.WIRETYPE_FIXED64:
2068 {
2069 long value = readRawLittleEndian64();
2070 output.writeRawVarint32(tag);
2071 output.writeFixed64NoTag(value);
2072 return true;
2073 }
2074 case WireFormat.WIRETYPE_LENGTH_DELIMITED:
2075 {
2076 ByteString value = readBytes();
2077 output.writeRawVarint32(tag);
2078 output.writeBytesNoTag(value);
2079 return true;
2080 }
2081 case WireFormat.WIRETYPE_START_GROUP:
2082 {
2083 output.writeRawVarint32(tag);
2084 skipMessage(output);
2085 int endtag =
2086 WireFormat.makeTag(
2087 WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_G ROUP);
2088 checkLastTagWas(endtag);
2089 output.writeRawVarint32(endtag);
2090 return true;
2091 }
2092 case WireFormat.WIRETYPE_END_GROUP:
2093 {
2094 return false;
2095 }
2096 case WireFormat.WIRETYPE_FIXED32:
2097 {
2098 int value = readRawLittleEndian32();
2099 output.writeRawVarint32(tag);
2100 output.writeFixed32NoTag(value);
2101 return true;
2102 }
2103 default:
2104 throw InvalidProtocolBufferException.invalidWireType();
2105 }
2106 }
2107
2108 @Override
2109 public void skipMessage() throws IOException {
2110 while (true) {
2111 final int tag = readTag();
2112 if (tag == 0 || !skipField(tag)) {
2113 return;
2114 }
2115 }
2116 }
2117
2118 @Override
2119 public void skipMessage(CodedOutputStream output) throws IOException {
2120 while (true) {
2121 final int tag = readTag();
2122 if (tag == 0 || !skipField(tag, output)) {
2123 return;
2124 }
2125 }
2126 }
2127
2128 /** Collects the bytes skipped and returns the data in a ByteBuffer. */
2129 private class SkippedDataSink implements RefillCallback {
2130 private int lastPos = pos;
2131 private ByteArrayOutputStream byteArrayStream;
2132
2133 @Override
2134 public void onRefill() {
2135 if (byteArrayStream == null) {
2136 byteArrayStream = new ByteArrayOutputStream();
2137 }
2138 byteArrayStream.write(buffer, lastPos, pos - lastPos);
2139 lastPos = 0;
2140 }
2141
2142 /** Gets skipped data in a ByteBuffer. This method should only be called o nce. */
2143 ByteBuffer getSkippedData() {
2144 if (byteArrayStream == null) {
2145 return ByteBuffer.wrap(buffer, lastPos, pos - lastPos);
2146 } else {
2147 byteArrayStream.write(buffer, lastPos, pos);
2148 return ByteBuffer.wrap(byteArrayStream.toByteArray());
2149 }
2150 }
2151 }
2152
2153
2154 // -----------------------------------------------------------------
2155
2156 @Override
2157 public double readDouble() throws IOException {
2158 return Double.longBitsToDouble(readRawLittleEndian64());
2159 }
2160
2161 @Override
2162 public float readFloat() throws IOException {
2163 return Float.intBitsToFloat(readRawLittleEndian32());
2164 }
2165
2166 @Override
2167 public long readUInt64() throws IOException {
2168 return readRawVarint64();
2169 }
2170
2171 @Override
2172 public long readInt64() throws IOException {
2173 return readRawVarint64();
2174 }
2175
2176 @Override
2177 public int readInt32() throws IOException {
2178 return readRawVarint32();
2179 }
2180
2181 @Override
2182 public long readFixed64() throws IOException {
2183 return readRawLittleEndian64();
2184 }
2185
2186 @Override
2187 public int readFixed32() throws IOException {
2188 return readRawLittleEndian32();
2189 }
2190
2191 @Override
2192 public boolean readBool() throws IOException {
2193 return readRawVarint64() != 0;
2194 }
2195
2196 @Override
2197 public String readString() throws IOException {
2198 final int size = readRawVarint32();
2199 if (size > 0 && size <= (bufferSize - pos)) {
2200 // Fast path: We already have the bytes in a contiguous buffer, so
2201 // just copy directly from it.
2202 final String result = new String(buffer, pos, size, UTF_8);
2203 pos += size;
2204 return result;
2205 }
2206 if (size == 0) {
2207 return "";
2208 }
2209 if (size <= bufferSize) {
2210 refillBuffer(size);
2211 String result = new String(buffer, pos, size, UTF_8);
2212 pos += size;
2213 return result;
2214 }
2215 // Slow path: Build a byte array first then copy it.
2216 return new String(readRawBytesSlowPath(size), UTF_8);
2217 }
2218
2219 @Override
2220 public String readStringRequireUtf8() throws IOException {
2221 final int size = readRawVarint32();
2222 final byte[] bytes;
2223 final int oldPos = pos;
2224 final int tempPos;
2225 if (size <= (bufferSize - oldPos) && size > 0) {
2226 // Fast path: We already have the bytes in a contiguous buffer, so
2227 // just copy directly from it.
2228 bytes = buffer;
2229 pos = oldPos + size;
2230 tempPos = oldPos;
2231 } else if (size == 0) {
2232 return "";
2233 } else if (size <= bufferSize) {
2234 refillBuffer(size);
2235 bytes = buffer;
2236 tempPos = 0;
2237 pos = tempPos + size;
2238 } else {
2239 // Slow path: Build a byte array first then copy it.
2240 bytes = readRawBytesSlowPath(size);
2241 tempPos = 0;
2242 }
2243 // TODO(martinrb): We could save a pass by validating while decoding.
2244 if (!Utf8.isValidUtf8(bytes, tempPos, tempPos + size)) {
2245 throw InvalidProtocolBufferException.invalidUtf8();
2246 }
2247 return new String(bytes, tempPos, size, UTF_8);
2248 }
2249
2250 @Override
2251 public void readGroup(
2252 final int fieldNumber,
2253 final MessageLite.Builder builder,
2254 final ExtensionRegistryLite extensionRegistry)
2255 throws IOException {
2256 if (recursionDepth >= recursionLimit) {
2257 throw InvalidProtocolBufferException.recursionLimitExceeded();
2258 }
2259 ++recursionDepth;
2260 builder.mergeFrom(this, extensionRegistry);
2261 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GR OUP));
2262 --recursionDepth;
2263 }
2264
2265
2266 @Override
2267 public <T extends MessageLite> T readGroup(
2268 final int fieldNumber,
2269 final Parser<T> parser,
2270 final ExtensionRegistryLite extensionRegistry)
2271 throws IOException {
2272 if (recursionDepth >= recursionLimit) {
2273 throw InvalidProtocolBufferException.recursionLimitExceeded();
2274 }
2275 ++recursionDepth;
2276 T result = parser.parsePartialFrom(this, extensionRegistry);
2277 checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GR OUP));
2278 --recursionDepth;
2279 return result;
2280 }
2281
2282 @Deprecated
2283 @Override
2284 public void readUnknownGroup(final int fieldNumber, final MessageLite.Builde r builder)
2285 throws IOException {
2286 readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
2287 }
2288
2289 @Override
2290 public void readMessage(
2291 final MessageLite.Builder builder, final ExtensionRegistryLite extension Registry)
2292 throws IOException {
2293 final int length = readRawVarint32();
2294 if (recursionDepth >= recursionLimit) {
2295 throw InvalidProtocolBufferException.recursionLimitExceeded();
2296 }
2297 final int oldLimit = pushLimit(length);
2298 ++recursionDepth;
2299 builder.mergeFrom(this, extensionRegistry);
2300 checkLastTagWas(0);
2301 --recursionDepth;
2302 popLimit(oldLimit);
2303 }
2304
2305
2306 @Override
2307 public <T extends MessageLite> T readMessage(
2308 final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) t hrows IOException {
2309 int length = readRawVarint32();
2310 if (recursionDepth >= recursionLimit) {
2311 throw InvalidProtocolBufferException.recursionLimitExceeded();
2312 }
2313 final int oldLimit = pushLimit(length);
2314 ++recursionDepth;
2315 T result = parser.parsePartialFrom(this, extensionRegistry);
2316 checkLastTagWas(0);
2317 --recursionDepth;
2318 popLimit(oldLimit);
2319 return result;
2320 }
2321
2322 @Override
2323 public ByteString readBytes() throws IOException {
2324 final int size = readRawVarint32();
2325 if (size <= (bufferSize - pos) && size > 0) {
2326 // Fast path: We already have the bytes in a contiguous buffer, so
2327 // just copy directly from it.
2328 final ByteString result = ByteString.copyFrom(buffer, pos, size);
2329 pos += size;
2330 return result;
2331 }
2332 if (size == 0) {
2333 return ByteString.EMPTY;
2334 }
2335 // Slow path: Build a byte array first then copy it.
2336 return ByteString.wrap(readRawBytesSlowPath(size));
2337 }
2338
2339 @Override
2340 public byte[] readByteArray() throws IOException {
2341 final int size = readRawVarint32();
2342 if (size <= (bufferSize - pos) && size > 0) {
2343 // Fast path: We already have the bytes in a contiguous buffer, so
2344 // just copy directly from it.
2345 final byte[] result = Arrays.copyOfRange(buffer, pos, pos + size);
2346 pos += size;
2347 return result;
2348 } else {
2349 // Slow path: Build a byte array first then copy it.
2350 return readRawBytesSlowPath(size);
2351 }
2352 }
2353
2354 @Override
2355 public ByteBuffer readByteBuffer() throws IOException {
2356 final int size = readRawVarint32();
2357 if (size <= (bufferSize - pos) && size > 0) {
2358 // Fast path: We already have the bytes in a contiguous buffer.
2359 ByteBuffer result = ByteBuffer.wrap(Arrays.copyOfRange(buffer, pos, pos + size));
2360 pos += size;
2361 return result;
2362 }
2363 if (size == 0) {
2364 return Internal.EMPTY_BYTE_BUFFER;
2365 }
2366 // Slow path: Build a byte array first then copy it.
2367 return ByteBuffer.wrap(readRawBytesSlowPath(size));
2368 }
2369
2370 @Override
2371 public int readUInt32() throws IOException {
2372 return readRawVarint32();
2373 }
2374
2375 @Override
2376 public int readEnum() throws IOException {
2377 return readRawVarint32();
2378 }
2379
2380 @Override
2381 public int readSFixed32() throws IOException {
2382 return readRawLittleEndian32();
2383 }
2384
2385 @Override
2386 public long readSFixed64() throws IOException {
2387 return readRawLittleEndian64();
2388 }
2389
2390 @Override
2391 public int readSInt32() throws IOException {
2392 return decodeZigZag32(readRawVarint32());
2393 }
2394
2395 @Override
2396 public long readSInt64() throws IOException {
2397 return decodeZigZag64(readRawVarint64());
2398 }
2399
2400 // =================================================================
2401
2402 @Override
2403 public int readRawVarint32() throws IOException {
2404 // See implementation notes for readRawVarint64
2405 fastpath:
2406 {
2407 int tempPos = pos;
2408
2409 if (bufferSize == tempPos) {
2410 break fastpath;
2411 }
2412
2413 final byte[] buffer = this.buffer;
2414 int x;
2415 if ((x = buffer[tempPos++]) >= 0) {
2416 pos = tempPos;
2417 return x;
2418 } else if (bufferSize - tempPos < 9) {
2419 break fastpath;
2420 } else if ((x ^= (buffer[tempPos++] << 7)) < 0) {
2421 x ^= (~0 << 7);
2422 } else if ((x ^= (buffer[tempPos++] << 14)) >= 0) {
2423 x ^= (~0 << 7) ^ (~0 << 14);
2424 } else if ((x ^= (buffer[tempPos++] << 21)) < 0) {
2425 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
2426 } else {
2427 int y = buffer[tempPos++];
2428 x ^= y << 28;
2429 x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
2430 if (y < 0
2431 && buffer[tempPos++] < 0
2432 && buffer[tempPos++] < 0
2433 && buffer[tempPos++] < 0
2434 && buffer[tempPos++] < 0
2435 && buffer[tempPos++] < 0) {
2436 break fastpath; // Will throw malformedVarint()
2437 }
2438 }
2439 pos = tempPos;
2440 return x;
2441 }
2442 return (int) readRawVarint64SlowPath();
2443 }
2444
2445 private void skipRawVarint() throws IOException {
2446 if (bufferSize - pos >= MAX_VARINT_SIZE) {
2447 skipRawVarintFastPath();
2448 } else {
2449 skipRawVarintSlowPath();
2450 }
2451 }
2452
2453 private void skipRawVarintFastPath() throws IOException {
2454 for (int i = 0; i < MAX_VARINT_SIZE; i++) {
2455 if (buffer[pos++] >= 0) {
2456 return;
2457 }
2458 }
2459 throw InvalidProtocolBufferException.malformedVarint();
2460 }
2461
2462 private void skipRawVarintSlowPath() throws IOException {
2463 for (int i = 0; i < MAX_VARINT_SIZE; i++) {
2464 if (readRawByte() >= 0) {
2465 return;
2466 }
2467 }
2468 throw InvalidProtocolBufferException.malformedVarint();
2469 }
2470
2471 @Override
2472 public long readRawVarint64() throws IOException {
2473 // Implementation notes:
2474 //
2475 // Optimized for one-byte values, expected to be common.
2476 // The particular code below was selected from various candidates
2477 // empirically, by winning VarintBenchmark.
2478 //
2479 // Sign extension of (signed) Java bytes is usually a nuisance, but
2480 // we exploit it here to more easily obtain the sign of bytes read.
2481 // Instead of cleaning up the sign extension bits by masking eagerly,
2482 // we delay until we find the final (positive) byte, when we clear all
2483 // accumulated bits with one xor. We depend on javac to constant fold.
2484 fastpath:
2485 {
2486 int tempPos = pos;
2487
2488 if (bufferSize == tempPos) {
2489 break fastpath;
2490 }
2491
2492 final byte[] buffer = this.buffer;
2493 long x;
2494 int y;
2495 if ((y = buffer[tempPos++]) >= 0) {
2496 pos = tempPos;
2497 return y;
2498 } else if (bufferSize - tempPos < 9) {
2499 break fastpath;
2500 } else if ((y ^= (buffer[tempPos++] << 7)) < 0) {
2501 x = y ^ (~0 << 7);
2502 } else if ((y ^= (buffer[tempPos++] << 14)) >= 0) {
2503 x = y ^ ((~0 << 7) ^ (~0 << 14));
2504 } else if ((y ^= (buffer[tempPos++] << 21)) < 0) {
2505 x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
2506 } else if ((x = y ^ ((long) buffer[tempPos++] << 28)) >= 0L) {
2507 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
2508 } else if ((x ^= ((long) buffer[tempPos++] << 35)) < 0L) {
2509 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35 );
2510 } else if ((x ^= ((long) buffer[tempPos++] << 42)) >= 0L) {
2511 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35 ) ^ (~0L << 42);
2512 } else if ((x ^= ((long) buffer[tempPos++] << 49)) < 0L) {
2513 x ^=
2514 (~0L << 7)
2515 ^ (~0L << 14)
2516 ^ (~0L << 21)
2517 ^ (~0L << 28)
2518 ^ (~0L << 35)
2519 ^ (~0L << 42)
2520 ^ (~0L << 49);
2521 } else {
2522 x ^= ((long) buffer[tempPos++] << 56);
2523 x ^=
2524 (~0L << 7)
2525 ^ (~0L << 14)
2526 ^ (~0L << 21)
2527 ^ (~0L << 28)
2528 ^ (~0L << 35)
2529 ^ (~0L << 42)
2530 ^ (~0L << 49)
2531 ^ (~0L << 56);
2532 if (x < 0L) {
2533 if (buffer[tempPos++] < 0L) {
2534 break fastpath; // Will throw malformedVarint()
2535 }
2536 }
2537 }
2538 pos = tempPos;
2539 return x;
2540 }
2541 return readRawVarint64SlowPath();
2542 }
2543
2544 @Override
2545 long readRawVarint64SlowPath() throws IOException {
2546 long result = 0;
2547 for (int shift = 0; shift < 64; shift += 7) {
2548 final byte b = readRawByte();
2549 result |= (long) (b & 0x7F) << shift;
2550 if ((b & 0x80) == 0) {
2551 return result;
2552 }
2553 }
2554 throw InvalidProtocolBufferException.malformedVarint();
2555 }
2556
2557 @Override
2558 public int readRawLittleEndian32() throws IOException {
2559 int tempPos = pos;
2560
2561 if (bufferSize - tempPos < FIXED_32_SIZE) {
2562 refillBuffer(FIXED_32_SIZE);
2563 tempPos = pos;
2564 }
2565
2566 final byte[] buffer = this.buffer;
2567 pos = tempPos + FIXED_32_SIZE;
2568 return (((buffer[tempPos] & 0xff))
2569 | ((buffer[tempPos + 1] & 0xff) << 8)
2570 | ((buffer[tempPos + 2] & 0xff) << 16)
2571 | ((buffer[tempPos + 3] & 0xff) << 24));
2572 }
2573
2574 @Override
2575 public long readRawLittleEndian64() throws IOException {
2576 int tempPos = pos;
2577
2578 if (bufferSize - tempPos < FIXED_64_SIZE) {
2579 refillBuffer(FIXED_64_SIZE);
2580 tempPos = pos;
2581 }
2582
2583 final byte[] buffer = this.buffer;
2584 pos = tempPos + FIXED_64_SIZE;
2585 return (((buffer[tempPos] & 0xffL))
2586 | ((buffer[tempPos + 1] & 0xffL) << 8)
2587 | ((buffer[tempPos + 2] & 0xffL) << 16)
2588 | ((buffer[tempPos + 3] & 0xffL) << 24)
2589 | ((buffer[tempPos + 4] & 0xffL) << 32)
2590 | ((buffer[tempPos + 5] & 0xffL) << 40)
2591 | ((buffer[tempPos + 6] & 0xffL) << 48)
2592 | ((buffer[tempPos + 7] & 0xffL) << 56));
2593 }
2594
2595 // -----------------------------------------------------------------
2596
2597 @Override
2598 public void enableAliasing(boolean enabled) {
2599 // TODO(nathanmittler): Ideally we should throw here. Do nothing for backw ard compatibility.
2600 }
2601
2602 @Override
2603 public void resetSizeCounter() {
2604 totalBytesRetired = -pos;
2605 }
2606
2607 @Override
2608 public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
2609 if (byteLimit < 0) {
2610 throw InvalidProtocolBufferException.negativeSize();
2611 }
2612 byteLimit += totalBytesRetired + pos;
2613 final int oldLimit = currentLimit;
2614 if (byteLimit > oldLimit) {
2615 throw InvalidProtocolBufferException.truncatedMessage();
2616 }
2617 currentLimit = byteLimit;
2618
2619 recomputeBufferSizeAfterLimit();
2620
2621 return oldLimit;
2622 }
2623
2624 private void recomputeBufferSizeAfterLimit() {
2625 bufferSize += bufferSizeAfterLimit;
2626 final int bufferEnd = totalBytesRetired + bufferSize;
2627 if (bufferEnd > currentLimit) {
2628 // Limit is in current buffer.
2629 bufferSizeAfterLimit = bufferEnd - currentLimit;
2630 bufferSize -= bufferSizeAfterLimit;
2631 } else {
2632 bufferSizeAfterLimit = 0;
2633 }
2634 }
2635
2636 @Override
2637 public void popLimit(final int oldLimit) {
2638 currentLimit = oldLimit;
2639 recomputeBufferSizeAfterLimit();
2640 }
2641
2642 @Override
2643 public int getBytesUntilLimit() {
2644 if (currentLimit == Integer.MAX_VALUE) {
2645 return -1;
2646 }
2647
2648 final int currentAbsolutePosition = totalBytesRetired + pos;
2649 return currentLimit - currentAbsolutePosition;
2650 }
2651
2652 @Override
2653 public boolean isAtEnd() throws IOException {
2654 return pos == bufferSize && !tryRefillBuffer(1);
2655 }
2656
2657 @Override
2658 public int getTotalBytesRead() {
2659 return totalBytesRetired + pos;
2660 }
2661
2662 private interface RefillCallback {
2663 void onRefill();
2664 }
2665
2666 private RefillCallback refillCallback = null;
2667
2668 /**
2669 * Reads more bytes from the input, making at least {@code n} bytes availabl e in the buffer.
2670 * Caller must ensure that the requested space is not yet available, and tha t the requested
2671 * space is less than BUFFER_SIZE.
2672 *
2673 * @throws InvalidProtocolBufferException The end of the stream or the curre nt limit was
2674 * reached.
2675 */
2676 private void refillBuffer(int n) throws IOException {
2677 if (!tryRefillBuffer(n)) {
2678 throw InvalidProtocolBufferException.truncatedMessage();
2679 }
2680 }
2681
2682 /**
2683 * Tries to read more bytes from the input, making at least {@code n} bytes available in the
2684 * buffer. Caller must ensure that the requested space is not yet available, and that the
2685 * requested space is less than BUFFER_SIZE.
2686 *
2687 * @return {@code true} if the bytes could be made available; {@code false} if the end of the
2688 * stream or the current limit was reached.
2689 */
2690 private boolean tryRefillBuffer(int n) throws IOException {
2691 if (pos + n <= bufferSize) {
2692 throw new IllegalStateException(
2693 "refillBuffer() called when " + n + " bytes were already available i n buffer");
2694 }
2695
2696 if (totalBytesRetired + pos + n > currentLimit) {
2697 // Oops, we hit a limit.
2698 return false;
2699 }
2700
2701 if (refillCallback != null) {
2702 refillCallback.onRefill();
2703 }
2704
2705 int tempPos = pos;
2706 if (tempPos > 0) {
2707 if (bufferSize > tempPos) {
2708 System.arraycopy(buffer, tempPos, buffer, 0, bufferSize - tempPos);
2709 }
2710 totalBytesRetired += tempPos;
2711 bufferSize -= tempPos;
2712 pos = 0;
1099 } 2713 }
1100 2714
1101 int bytesRead = input.read(buffer, bufferSize, buffer.length - bufferSize) ; 2715 int bytesRead = input.read(buffer, bufferSize, buffer.length - bufferSize) ;
1102 if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) { 2716 if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) {
1103 throw new IllegalStateException( 2717 throw new IllegalStateException(
1104 "InputStream#read(byte[]) returned invalid result: " + bytesRead + 2718 "InputStream#read(byte[]) returned invalid result: "
1105 "\nThe InputStream implementation is buggy."); 2719 + bytesRead
2720 + "\nThe InputStream implementation is buggy.");
1106 } 2721 }
1107 if (bytesRead > 0) { 2722 if (bytesRead > 0) {
1108 bufferSize += bytesRead; 2723 bufferSize += bytesRead;
1109 // Integer-overflow-conscious check against sizeLimit 2724 // Integer-overflow-conscious check against sizeLimit
1110 if (totalBytesRetired + n - sizeLimit > 0) { 2725 if (totalBytesRetired + n - sizeLimit > 0) {
1111 throw InvalidProtocolBufferException.sizeLimitExceeded(); 2726 throw InvalidProtocolBufferException.sizeLimitExceeded();
1112 } 2727 }
1113 recomputeBufferSizeAfterLimit(); 2728 recomputeBufferSizeAfterLimit();
1114 return (bufferSize >= n) ? true : tryRefillBuffer(n); 2729 return (bufferSize >= n) ? true : tryRefillBuffer(n);
1115 } 2730 }
1116 } 2731
1117 2732 return false;
1118 return false; 2733 }
1119 } 2734
1120 2735 @Override
1121 /** 2736 public byte readRawByte() throws IOException {
1122 * Read one byte from the input. 2737 if (pos == bufferSize) {
1123 * 2738 refillBuffer(1);
1124 * @throws InvalidProtocolBufferException The end of the stream or the current 2739 }
1125 * limit was reached. 2740 return buffer[pos++];
1126 */ 2741 }
1127 public byte readRawByte() throws IOException { 2742
1128 if (bufferPos == bufferSize) { 2743 @Override
1129 refillBuffer(1); 2744 public byte[] readRawBytes(final int size) throws IOException {
1130 } 2745 final int tempPos = pos;
1131 return buffer[bufferPos++]; 2746 if (size <= (bufferSize - tempPos) && size > 0) {
1132 } 2747 pos = tempPos + size;
1133 2748 return Arrays.copyOfRange(buffer, tempPos, tempPos + size);
1134 /** 2749 } else {
1135 * Read a fixed size of bytes from the input. 2750 return readRawBytesSlowPath(size);
1136 * 2751 }
1137 * @throws InvalidProtocolBufferException The end of the stream or the current 2752 }
1138 * limit was reached. 2753
1139 */ 2754 /**
1140 public byte[] readRawBytes(final int size) throws IOException { 2755 * Exactly like readRawBytes, but caller must have already checked the fast path: (size <=
1141 final int pos = bufferPos; 2756 * (bufferSize - pos) && size > 0)
1142 if (size <= (bufferSize - pos) && size > 0) { 2757 */
1143 bufferPos = pos + size; 2758 private byte[] readRawBytesSlowPath(final int size) throws IOException {
1144 return Arrays.copyOfRange(buffer, pos, pos + size);
1145 } else {
1146 return readRawBytesSlowPath(size);
1147 }
1148 }
1149
1150 /**
1151 * Exactly like readRawBytes, but caller must have already checked the fast
1152 * path: (size <= (bufferSize - pos) && size > 0)
1153 */
1154 private byte[] readRawBytesSlowPath(final int size) throws IOException {
1155 if (size <= 0) {
1156 if (size == 0) { 2759 if (size == 0) {
1157 return Internal.EMPTY_BYTE_ARRAY; 2760 return Internal.EMPTY_BYTE_ARRAY;
2761 }
2762 if (size < 0) {
2763 throw InvalidProtocolBufferException.negativeSize();
2764 }
2765
2766 // Integer-overflow-conscious check that the message size so far has not e xceeded sizeLimit.
2767 int currentMessageSize = totalBytesRetired + pos + size;
2768 if (currentMessageSize - sizeLimit > 0) {
2769 throw InvalidProtocolBufferException.sizeLimitExceeded();
2770 }
2771
2772 // Verify that the message size so far has not exceeded currentLimit.
2773 if (currentMessageSize > currentLimit) {
2774 // Read to the end of the stream anyway.
2775 skipRawBytes(currentLimit - totalBytesRetired - pos);
2776 throw InvalidProtocolBufferException.truncatedMessage();
2777 }
2778
2779 final int originalBufferPos = pos;
2780 final int bufferedBytes = bufferSize - pos;
2781
2782 // Mark the current buffer consumed.
2783 totalBytesRetired += bufferSize;
2784 pos = 0;
2785 bufferSize = 0;
2786
2787 // Determine the number of bytes we need to read from the input stream.
2788 int sizeLeft = size - bufferedBytes;
2789 // TODO(nathanmittler): Consider using a value larger than DEFAULT_BUFFER_ SIZE.
2790 if (sizeLeft < DEFAULT_BUFFER_SIZE || sizeLeft <= input.available()) {
2791 // Either the bytes we need are known to be available, or the required b uffer is
2792 // within an allowed threshold - go ahead and allocate the buffer now.
2793 final byte[] bytes = new byte[size];
2794
2795 // Copy all of the buffered bytes to the result buffer.
2796 System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
2797
2798 // Fill the remaining bytes from the input stream.
2799 int tempPos = bufferedBytes;
2800 while (tempPos < bytes.length) {
2801 int n = input.read(bytes, tempPos, size - tempPos);
2802 if (n == -1) {
2803 throw InvalidProtocolBufferException.truncatedMessage();
2804 }
2805 totalBytesRetired += n;
2806 tempPos += n;
2807 }
2808
2809 return bytes;
2810 }
2811
2812 // The size is very large. For security reasons, we can't allocate the
2813 // entire byte array yet. The size comes directly from the input, so a
2814 // maliciously-crafted message could provide a bogus very large size in
2815 // order to trick the app into allocating a lot of memory. We avoid this
2816 // by allocating and reading only a small chunk at a time, so that the
2817 // malicious message must actually *be* extremely large to cause
2818 // problems. Meanwhile, we limit the allowed size of a message elsewhere.
2819 final List<byte[]> chunks = new ArrayList<byte[]>();
2820
2821 while (sizeLeft > 0) {
2822 // TODO(nathanmittler): Consider using a value larger than DEFAULT_BUFFE R_SIZE.
2823 final byte[] chunk = new byte[Math.min(sizeLeft, DEFAULT_BUFFER_SIZE)];
2824 int tempPos = 0;
2825 while (tempPos < chunk.length) {
2826 final int n = input.read(chunk, tempPos, chunk.length - tempPos);
2827 if (n == -1) {
2828 throw InvalidProtocolBufferException.truncatedMessage();
2829 }
2830 totalBytesRetired += n;
2831 tempPos += n;
2832 }
2833 sizeLeft -= chunk.length;
2834 chunks.add(chunk);
2835 }
2836
2837 // OK, got everything. Now concatenate it all into one buffer.
2838 final byte[] bytes = new byte[size];
2839
2840 // Start by copying the leftover bytes from this.buffer.
2841 System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
2842
2843 // And now all the chunks.
2844 int tempPos = bufferedBytes;
2845 for (final byte[] chunk : chunks) {
2846 System.arraycopy(chunk, 0, bytes, tempPos, chunk.length);
2847 tempPos += chunk.length;
2848 }
2849
2850 // Done.
2851 return bytes;
2852 }
2853
2854 @Override
2855 public void skipRawBytes(final int size) throws IOException {
2856 if (size <= (bufferSize - pos) && size >= 0) {
2857 // We have all the bytes we need already.
2858 pos += size;
1158 } else { 2859 } else {
2860 skipRawBytesSlowPath(size);
2861 }
2862 }
2863
2864 /**
2865 * Exactly like skipRawBytes, but caller must have already checked the fast path: (size <=
2866 * (bufferSize - pos) && size >= 0)
2867 */
2868 private void skipRawBytesSlowPath(final int size) throws IOException {
2869 if (size < 0) {
1159 throw InvalidProtocolBufferException.negativeSize(); 2870 throw InvalidProtocolBufferException.negativeSize();
1160 } 2871 }
1161 } 2872
1162 2873 if (totalBytesRetired + pos + size > currentLimit) {
1163 // Verify that the message size so far has not exceeded sizeLimit. 2874 // Read to the end of the stream anyway.
1164 int currentMessageSize = totalBytesRetired + bufferPos + size; 2875 skipRawBytes(currentLimit - totalBytesRetired - pos);
1165 if (currentMessageSize > sizeLimit) { 2876 // Then fail.
1166 throw InvalidProtocolBufferException.sizeLimitExceeded(); 2877 throw InvalidProtocolBufferException.truncatedMessage();
1167 } 2878 }
1168 2879
1169 // Verify that the message size so far has not exceeded currentLimit. 2880 // Skipping more bytes than are in the buffer. First skip what we have.
1170 if (currentMessageSize > currentLimit) { 2881 int tempPos = bufferSize - pos;
1171 // Read to the end of the stream anyway. 2882 pos = bufferSize;
1172 skipRawBytes(currentLimit - totalBytesRetired - bufferPos); 2883
1173 throw InvalidProtocolBufferException.truncatedMessage(); 2884 // Keep refilling the buffer until we get to the point we wanted to skip t o.
1174 } 2885 // This has the side effect of ensuring the limits are updated correctly.
1175
1176 // We need the input stream to proceed.
1177 if (input == null) {
1178 throw InvalidProtocolBufferException.truncatedMessage();
1179 }
1180
1181 final int originalBufferPos = bufferPos;
1182 final int bufferedBytes = bufferSize - bufferPos;
1183
1184 // Mark the current buffer consumed.
1185 totalBytesRetired += bufferSize;
1186 bufferPos = 0;
1187 bufferSize = 0;
1188
1189 // Determine the number of bytes we need to read from the input stream.
1190 int sizeLeft = size - bufferedBytes;
1191 // TODO(nathanmittler): Consider using a value larger than BUFFER_SIZE.
1192 if (sizeLeft < BUFFER_SIZE || sizeLeft <= input.available()) {
1193 // Either the bytes we need are known to be available, or the required buf fer is
1194 // within an allowed threshold - go ahead and allocate the buffer now.
1195 final byte[] bytes = new byte[size];
1196
1197 // Copy all of the buffered bytes to the result buffer.
1198 System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
1199
1200 // Fill the remaining bytes from the input stream.
1201 int pos = bufferedBytes;
1202 while (pos < bytes.length) {
1203 int n = input.read(bytes, pos, size - pos);
1204 if (n == -1) {
1205 throw InvalidProtocolBufferException.truncatedMessage();
1206 }
1207 totalBytesRetired += n;
1208 pos += n;
1209 }
1210
1211 return bytes;
1212 }
1213
1214 // The size is very large. For security reasons, we can't allocate the
1215 // entire byte array yet. The size comes directly from the input, so a
1216 // maliciously-crafted message could provide a bogus very large size in
1217 // order to trick the app into allocating a lot of memory. We avoid this
1218 // by allocating and reading only a small chunk at a time, so that the
1219 // malicious message must actually *be* extremely large to cause
1220 // problems. Meanwhile, we limit the allowed size of a message elsewhere.
1221 final List<byte[]> chunks = new ArrayList<byte[]>();
1222
1223 while (sizeLeft > 0) {
1224 // TODO(nathanmittler): Consider using a value larger than BUFFER_SIZE.
1225 final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
1226 int pos = 0;
1227 while (pos < chunk.length) {
1228 final int n = input.read(chunk, pos, chunk.length - pos);
1229 if (n == -1) {
1230 throw InvalidProtocolBufferException.truncatedMessage();
1231 }
1232 totalBytesRetired += n;
1233 pos += n;
1234 }
1235 sizeLeft -= chunk.length;
1236 chunks.add(chunk);
1237 }
1238
1239 // OK, got everything. Now concatenate it all into one buffer.
1240 final byte[] bytes = new byte[size];
1241
1242 // Start by copying the leftover bytes from this.buffer.
1243 System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
1244
1245 // And now all the chunks.
1246 int pos = bufferedBytes;
1247 for (final byte[] chunk : chunks) {
1248 System.arraycopy(chunk, 0, bytes, pos, chunk.length);
1249 pos += chunk.length;
1250 }
1251
1252 // Done.
1253 return bytes;
1254 }
1255
1256 /**
1257 * Reads and discards {@code size} bytes.
1258 *
1259 * @throws InvalidProtocolBufferException The end of the stream or the current
1260 * limit was reached.
1261 */
1262 public void skipRawBytes(final int size) throws IOException {
1263 if (size <= (bufferSize - bufferPos) && size >= 0) {
1264 // We have all the bytes we need already.
1265 bufferPos += size;
1266 } else {
1267 skipRawBytesSlowPath(size);
1268 }
1269 }
1270
1271 /**
1272 * Exactly like skipRawBytes, but caller must have already checked the fast
1273 * path: (size <= (bufferSize - pos) && size >= 0)
1274 */
1275 private void skipRawBytesSlowPath(final int size) throws IOException {
1276 if (size < 0) {
1277 throw InvalidProtocolBufferException.negativeSize();
1278 }
1279
1280 if (totalBytesRetired + bufferPos + size > currentLimit) {
1281 // Read to the end of the stream anyway.
1282 skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
1283 // Then fail.
1284 throw InvalidProtocolBufferException.truncatedMessage();
1285 }
1286
1287 // Skipping more bytes than are in the buffer. First skip what we have.
1288 int pos = bufferSize - bufferPos;
1289 bufferPos = bufferSize;
1290
1291 // Keep refilling the buffer until we get to the point we wanted to skip to.
1292 // This has the side effect of ensuring the limits are updated correctly.
1293 refillBuffer(1);
1294 while (size - pos > bufferSize) {
1295 pos += bufferSize;
1296 bufferPos = bufferSize;
1297 refillBuffer(1); 2886 refillBuffer(1);
1298 } 2887 while (size - tempPos > bufferSize) {
1299 2888 tempPos += bufferSize;
1300 bufferPos = size - pos; 2889 pos = bufferSize;
2890 refillBuffer(1);
2891 }
2892
2893 pos = size - tempPos;
2894 }
1301 } 2895 }
1302 } 2896 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698