@Override public void skipRawBytes(final int length) throws IOException { if (length >= 0 && length <= (limit - pos)) { // We have all the bytes we need already. pos += length; return; } if (length < 0) { throw InvalidProtocolBufferException.negativeSize(); } throw InvalidProtocolBufferException.truncatedMessage(); } }
@Override public byte[] readRawBytes(final int length) throws IOException { if (length > 0 && length <= (limit - pos)) { final int tempPos = pos; pos += length; return Arrays.copyOfRange(buffer, tempPos, pos); } if (length <= 0) { if (length == 0) { return Internal.EMPTY_BYTE_ARRAY; } else { throw InvalidProtocolBufferException.negativeSize(); } } throw InvalidProtocolBufferException.truncatedMessage(); }
@Override public void skipRawBytes(final int length) throws IOException { if (length >= 0 && length <= remaining()) { // We have all the bytes we need already. pos += length; return; } if (length < 0) { throw InvalidProtocolBufferException.negativeSize(); } throw InvalidProtocolBufferException.truncatedMessage(); }
@Override public ByteBuffer readByteBuffer() throws IOException { final int size = readRawVarint32(); if (size > 0 && size <= (limit - pos)) { // Fast path: We already have the bytes in a contiguous buffer. // When aliasing is enabled, we can return a ByteBuffer pointing directly // into the underlying byte array without copy if the CodedInputStream is // constructed from a byte array. If aliasing is disabled or the input is // from an InputStream or ByteString, we have to make a copy of the bytes. ByteBuffer result = !immutable && enableAliasing ? ByteBuffer.wrap(buffer, pos, size).slice() : ByteBuffer.wrap(Arrays.copyOfRange(buffer, pos, pos + size)); pos += size; // TODO(nathanmittler): Investigate making the ByteBuffer be made read-only return result; } if (size == 0) { return EMPTY_BYTE_BUFFER; } if (size < 0) { throw InvalidProtocolBufferException.negativeSize(); } throw InvalidProtocolBufferException.truncatedMessage(); }
@Override public String readString() throws IOException { final int size = readRawVarint32(); if (size > 0 && size <= (limit - pos)) { // Fast path: We already have the bytes in a contiguous buffer, so // just copy directly from it. final String result = new String(buffer, pos, size, UTF_8); pos += size; return result; } if (size == 0) { return ""; } if (size < 0) { throw InvalidProtocolBufferException.negativeSize(); } throw InvalidProtocolBufferException.truncatedMessage(); }
@Override public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { if (byteLimit < 0) { throw InvalidProtocolBufferException.negativeSize(); } byteLimit += totalBytesRetired + pos; final int oldLimit = currentLimit; if (byteLimit > oldLimit) { throw InvalidProtocolBufferException.truncatedMessage(); } currentLimit = byteLimit; recomputeBufferSizeAfterLimit(); return oldLimit; }
@Override public byte[] readRawBytes(final int length) throws IOException { if (length >= 0 && length <= remaining()) { byte[] bytes = new byte[length]; slice(pos, pos + length).get(bytes); pos += length; return bytes; } if (length <= 0) { if (length == 0) { return EMPTY_BYTE_ARRAY; } else { throw InvalidProtocolBufferException.negativeSize(); } } throw InvalidProtocolBufferException.truncatedMessage(); }
@Override public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { if (byteLimit < 0) { throw InvalidProtocolBufferException.negativeSize(); } byteLimit += getTotalBytesRead(); final int oldLimit = currentLimit; if (byteLimit > oldLimit) { throw InvalidProtocolBufferException.truncatedMessage(); } currentLimit = byteLimit; recomputeBufferSizeAfterLimit(); return oldLimit; }
/** * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This * is called when descending into a length-delimited embedded message. * * <p>Note that {@code pushLimit()} does NOT affect how many bytes the * {@code CodedInputStream} reads from an underlying {@code InputStream} when * refreshing its buffer. If you need to prevent reading past a certain * point in the underlying {@code InputStream} (e.g. because you expect it to * contain more data after the end of the message which you need to handle * differently) then you must place a wrapper around your {@code InputStream} * which limits the amount of data that can be read from it. * * @return the old limit. */ public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { if (byteLimit < 0) { throw InvalidProtocolBufferException.negativeSize(); } byteLimit += totalBytesRetired + bufferPos; final int oldLimit = currentLimit; if (byteLimit > oldLimit) { throw InvalidProtocolBufferException.truncatedMessage(); } currentLimit = byteLimit; recomputeBufferSizeAfterLimit(); return oldLimit; }
@Override public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { if (byteLimit < 0) { throw InvalidProtocolBufferException.negativeSize(); } byteLimit += getTotalBytesRead(); final int oldLimit = currentLimit; if (byteLimit > oldLimit) { throw InvalidProtocolBufferException.truncatedMessage(); } currentLimit = byteLimit; recomputeBufferSizeAfterLimit(); return oldLimit; }
@Override public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { if (byteLimit < 0) { throw InvalidProtocolBufferException.negativeSize(); } byteLimit += getTotalBytesRead(); final int oldLimit = currentLimit; if (byteLimit > oldLimit) { throw InvalidProtocolBufferException.truncatedMessage(); } currentLimit = byteLimit; recomputeBufferSizeAfterLimit(); return oldLimit; }
@Override public String readString() throws IOException { final int size = readRawVarint32(); if (size > 0 && size <= remaining()) { // TODO(nathanmittler): Is there a way to avoid this copy? // TODO(anuraaga): It might be possible to share the optimized loop with // readStringRequireUtf8 by implementing Java replacement logic there. // The same as readBytes' logic byte[] bytes = new byte[size]; UnsafeUtil.copyMemory(pos, bytes, 0, size); String result = new String(bytes, UTF_8); pos += size; return result; } if (size == 0) { return ""; } if (size < 0) { throw InvalidProtocolBufferException.negativeSize(); } throw InvalidProtocolBufferException.truncatedMessage(); }
@Override public String readString() throws IOException { final int size = readRawVarint32(); if (size > 0 && size <= currentByteBufferLimit - currentByteBufferPos) { byte[] bytes = new byte[size]; UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size); String result = new String(bytes, UTF_8); currentByteBufferPos += size; return result; } else if (size > 0 && size <= remaining()) { // TODO(yilunchong): To use an underlying bytes[] instead of allocating a new bytes[] byte[] bytes = new byte[size]; readRawBytesTo(bytes, 0, size); String result = new String(bytes, UTF_8); return result; } if (size == 0) { return ""; } if (size < 0) { throw InvalidProtocolBufferException.negativeSize(); } throw InvalidProtocolBufferException.truncatedMessage(); }
@Override public void skipRawBytes(final int length) throws IOException { if (length >= 0 && length <= (totalBufferSize - totalBytesRead - currentByteBufferPos + currentByteBufferStartPos)) { // We have all the bytes we need already. int l = length; while (l > 0) { if (currentRemaining() == 0) { getNextByteBuffer(); } int rl = Math.min(l, (int) currentRemaining()); l -= rl; currentByteBufferPos += rl; } return; } if (length < 0) { throw InvalidProtocolBufferException.negativeSize(); } throw InvalidProtocolBufferException.truncatedMessage(); }
@Override public String readStringRequireUtf8() throws IOException { final int size = readRawVarint32(); if (size > 0 && size <= (limit - pos)) { if (ENABLE_CUSTOM_UTF8_DECODE) { String result = Utf8.decodeUtf8(buffer, pos, size); pos += size; return result; } else { // TODO(martinrb): We could save a pass by validating while decoding. if (!Utf8.isValidUtf8(buffer, pos, pos + size)) { throw InvalidProtocolBufferException.invalidUtf8(); } final int tempPos = pos; pos += size; return new String(buffer, tempPos, size, UTF_8); } } if (size == 0) { return ""; } if (size <= 0) { throw InvalidProtocolBufferException.negativeSize(); } throw InvalidProtocolBufferException.truncatedMessage(); }
@Override public ByteBuffer readByteBuffer() throws IOException { final int size = readRawVarint32(); if (size > 0 && size <= remaining()) { // "Immutable" implies that buffer is backing a ByteString. // Disallow slicing in this case to prevent the caller from modifying the contents // of the ByteString. if (!immutable && enableAliasing) { final ByteBuffer result = slice(pos, pos + size); pos += size; return result; } else { // The same as readBytes' logic byte[] bytes = new byte[size]; UnsafeUtil.copyMemory(pos, bytes, 0, size); pos += size; return ByteBuffer.wrap(bytes); } // TODO(nathanmittler): Investigate making the ByteBuffer be made read-only } if (size == 0) { return EMPTY_BYTE_BUFFER; } if (size < 0) { throw InvalidProtocolBufferException.negativeSize(); } throw InvalidProtocolBufferException.truncatedMessage(); }
@Override public ByteBuffer readByteBuffer() throws IOException { final int size = readRawVarint32(); if (size > 0 && size <= currentRemaining()) { if (!immutable && enableAliasing) { currentByteBufferPos += size; return slice( (int) (currentByteBufferPos - currentAddress - size), (int) (currentByteBufferPos - currentAddress)); } else { byte[] bytes = new byte[size]; UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, size); currentByteBufferPos += size; return ByteBuffer.wrap(bytes); } } else if (size > 0 && size <= remaining()) { byte[] temp = new byte[size]; readRawBytesTo(temp, 0, size); return ByteBuffer.wrap(temp); } if (size == 0) { return EMPTY_BYTE_BUFFER; } if (size < 0) { throw InvalidProtocolBufferException.negativeSize(); } throw InvalidProtocolBufferException.truncatedMessage(); }
/** * Exactly like skipRawBytes, but caller must have already checked the fast path: (size <= * (bufferSize - pos) && size >= 0) */ private void skipRawBytesSlowPath(final int size) throws IOException { if (size < 0) { throw InvalidProtocolBufferException.negativeSize(); } if (totalBytesRetired + pos + size > currentLimit) { // Read to the end of the stream anyway. skipRawBytes(currentLimit - totalBytesRetired - pos); // Then fail. throw InvalidProtocolBufferException.truncatedMessage(); } // Skipping more bytes than are in the buffer. First skip what we have. int tempPos = bufferSize - pos; pos = bufferSize; // Keep refilling the buffer until we get to the point we wanted to skip to. // This has the side effect of ensuring the limits are updated correctly. refillBuffer(1); while (size - tempPos > bufferSize) { tempPos += bufferSize; pos = bufferSize; refillBuffer(1); } pos = size - tempPos; } }
@Override public byte[] readRawBytes(final int length) throws IOException { if (length >= 0 && length <= currentRemaining()) { byte[] bytes = new byte[length]; UnsafeUtil.copyMemory(currentByteBufferPos, bytes, 0, length); currentByteBufferPos += length; return bytes; } if (length >= 0 && length <= remaining()) { byte[] bytes = new byte[length]; readRawBytesTo(bytes, 0, length); return bytes; } if (length <= 0) { if (length == 0) { return EMPTY_BYTE_ARRAY; } else { throw InvalidProtocolBufferException.negativeSize(); } } throw InvalidProtocolBufferException.truncatedMessage(); }
@Override public ByteString readBytes() throws IOException { final int size = readRawVarint32(); if (size > 0 && size <= remaining()) { if (immutable && enableAliasing) { final ByteBuffer result = slice(pos, pos + size); pos += size; return ByteString.wrap(result); } else { // Use UnsafeUtil to copy the memory to bytes instead of using ByteBuffer ways. byte[] bytes = new byte[size]; UnsafeUtil.copyMemory(pos, bytes, 0, size); pos += size; return ByteString.wrap(bytes); } } if (size == 0) { return ByteString.EMPTY; } if (size < 0) { throw InvalidProtocolBufferException.negativeSize(); } throw InvalidProtocolBufferException.truncatedMessage(); }