Like micro protobufs except: - No setter/getter/hazzer functions. - Has state is not available. Outputs all fields != their default. - CodedInputStream can only take byte[] (not InputStream). - Repeated fields are in arrays, not ArrayList or Vector. - Unset messages/groups are null, not "defaultInstance()". - Required fields are always serialized. To use: - Link libprotobuf-java-2.3.0-nano runtime. - Use LOCAL_PROTOC_OPTIMIZE_TYPE := nano Change-Id: I7429015b3c5f7f38b7be01eb2d4927f7a9999c80pull/91/head
parent
c4e73a82ff
commit
d6592c758c
33 changed files with 7904 additions and 0 deletions
@ -0,0 +1,624 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2013 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
package com.google.protobuf.nano; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Reads and decodes protocol message fields. |
||||||
|
* |
||||||
|
* This class contains two kinds of methods: methods that read specific |
||||||
|
* protocol message constructs and field types (e.g. {@link #readTag()} and |
||||||
|
* {@link #readInt32()}) and methods that read low-level values (e.g. |
||||||
|
* {@link #readRawVarint32()} and {@link #readRawBytes}). If you are reading |
||||||
|
* encoded protocol messages, you should use the former methods, but if you are |
||||||
|
* reading some other format of your own design, use the latter. |
||||||
|
* |
||||||
|
* @author kenton@google.com Kenton Varda |
||||||
|
*/ |
||||||
|
public final class CodedInputByteBufferNano { |
||||||
|
/** |
||||||
|
* Create a new CodedInputStream wrapping the given byte array. |
||||||
|
*/ |
||||||
|
public static CodedInputByteBufferNano newInstance(final byte[] buf) { |
||||||
|
return newInstance(buf, 0, buf.length); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new CodedInputStream wrapping the given byte array slice. |
||||||
|
*/ |
||||||
|
public static CodedInputByteBufferNano newInstance(final byte[] buf, final int off, |
||||||
|
final int len) { |
||||||
|
return new CodedInputByteBufferNano(buf, off, len); |
||||||
|
} |
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
/** |
||||||
|
* Attempt to read a field tag, returning zero if we have reached EOF. |
||||||
|
* Protocol message parsers use this to read tags, since a protocol message |
||||||
|
* may legally end wherever a tag occurs, and zero is not a valid tag number. |
||||||
|
*/ |
||||||
|
public int readTag() throws IOException { |
||||||
|
if (isAtEnd()) { |
||||||
|
lastTag = 0; |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
lastTag = readRawVarint32(); |
||||||
|
if (lastTag == 0) { |
||||||
|
// If we actually read zero, that's not a valid tag.
|
||||||
|
throw InvalidProtocolBufferNanoException.invalidTag(); |
||||||
|
} |
||||||
|
return lastTag; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Verifies that the last call to readTag() returned the given tag value. |
||||||
|
* This is used to verify that a nested group ended with the correct |
||||||
|
* end tag. |
||||||
|
* |
||||||
|
* @throws InvalidProtocolBufferNanoException {@code value} does not match the |
||||||
|
* last tag. |
||||||
|
*/ |
||||||
|
public void checkLastTagWas(final int value) |
||||||
|
throws InvalidProtocolBufferNanoException { |
||||||
|
if (lastTag != value) { |
||||||
|
throw InvalidProtocolBufferNanoException.invalidEndTag(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Reads and discards a single field, given its tag value. |
||||||
|
* |
||||||
|
* @return {@code false} if the tag is an endgroup tag, in which case |
||||||
|
* nothing is skipped. Otherwise, returns {@code true}. |
||||||
|
*/ |
||||||
|
public boolean skipField(final int tag) throws IOException { |
||||||
|
switch (WireFormatNano.getTagWireType(tag)) { |
||||||
|
case WireFormatNano.WIRETYPE_VARINT: |
||||||
|
readInt32(); |
||||||
|
return true; |
||||||
|
case WireFormatNano.WIRETYPE_FIXED64: |
||||||
|
readRawLittleEndian64(); |
||||||
|
return true; |
||||||
|
case WireFormatNano.WIRETYPE_LENGTH_DELIMITED: |
||||||
|
skipRawBytes(readRawVarint32()); |
||||||
|
return true; |
||||||
|
case WireFormatNano.WIRETYPE_START_GROUP: |
||||||
|
skipMessage(); |
||||||
|
checkLastTagWas( |
||||||
|
WireFormatNano.makeTag(WireFormatNano.getTagFieldNumber(tag), |
||||||
|
WireFormatNano.WIRETYPE_END_GROUP)); |
||||||
|
return true; |
||||||
|
case WireFormatNano.WIRETYPE_END_GROUP: |
||||||
|
return false; |
||||||
|
case WireFormatNano.WIRETYPE_FIXED32: |
||||||
|
readRawLittleEndian32(); |
||||||
|
return true; |
||||||
|
default: |
||||||
|
throw InvalidProtocolBufferNanoException.invalidWireType(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Reads and discards an entire message. This will read either until EOF |
||||||
|
* or until an endgroup tag, whichever comes first. |
||||||
|
*/ |
||||||
|
public void skipMessage() throws IOException { |
||||||
|
while (true) { |
||||||
|
final int tag = readTag(); |
||||||
|
if (tag == 0 || !skipField(tag)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Read a {@code double} field value from the stream. */ |
||||||
|
public double readDouble() throws IOException { |
||||||
|
return Double.longBitsToDouble(readRawLittleEndian64()); |
||||||
|
} |
||||||
|
|
||||||
|
/** Read a {@code float} field value from the stream. */ |
||||||
|
public float readFloat() throws IOException { |
||||||
|
return Float.intBitsToFloat(readRawLittleEndian32()); |
||||||
|
} |
||||||
|
|
||||||
|
/** Read a {@code uint64} field value from the stream. */ |
||||||
|
public long readUInt64() throws IOException { |
||||||
|
return readRawVarint64(); |
||||||
|
} |
||||||
|
|
||||||
|
/** Read an {@code int64} field value from the stream. */ |
||||||
|
public long readInt64() throws IOException { |
||||||
|
return readRawVarint64(); |
||||||
|
} |
||||||
|
|
||||||
|
/** Read an {@code int32} field value from the stream. */ |
||||||
|
public int readInt32() throws IOException { |
||||||
|
return readRawVarint32(); |
||||||
|
} |
||||||
|
|
||||||
|
/** Read a {@code fixed64} field value from the stream. */ |
||||||
|
public long readFixed64() throws IOException { |
||||||
|
return readRawLittleEndian64(); |
||||||
|
} |
||||||
|
|
||||||
|
/** Read a {@code fixed32} field value from the stream. */ |
||||||
|
public int readFixed32() throws IOException { |
||||||
|
return readRawLittleEndian32(); |
||||||
|
} |
||||||
|
|
||||||
|
/** Read a {@code bool} field value from the stream. */ |
||||||
|
public boolean readBool() throws IOException { |
||||||
|
return readRawVarint32() != 0; |
||||||
|
} |
||||||
|
|
||||||
|
/** Read a {@code string} field value from the stream. */ |
||||||
|
public String readString() throws IOException { |
||||||
|
final int size = readRawVarint32(); |
||||||
|
if (size <= (bufferSize - bufferPos) && size > 0) { |
||||||
|
// Fast path: We already have the bytes in a contiguous buffer, so
|
||||||
|
// just copy directly from it.
|
||||||
|
final String result = new String(buffer, bufferPos, size, "UTF-8"); |
||||||
|
bufferPos += size; |
||||||
|
return result; |
||||||
|
} else { |
||||||
|
// Slow path: Build a byte array first then copy it.
|
||||||
|
return new String(readRawBytes(size), "UTF-8"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** Read a {@code group} field value from the stream. */ |
||||||
|
public void readGroup(final MessageNano msg, final int fieldNumber) |
||||||
|
throws IOException { |
||||||
|
if (recursionDepth >= recursionLimit) { |
||||||
|
throw InvalidProtocolBufferNanoException.recursionLimitExceeded(); |
||||||
|
} |
||||||
|
++recursionDepth; |
||||||
|
msg.mergeFrom(this); |
||||||
|
checkLastTagWas( |
||||||
|
WireFormatNano.makeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP)); |
||||||
|
--recursionDepth; |
||||||
|
} |
||||||
|
|
||||||
|
public void readMessage(final MessageNano msg) |
||||||
|
throws IOException { |
||||||
|
final int length = readRawVarint32(); |
||||||
|
if (recursionDepth >= recursionLimit) { |
||||||
|
throw InvalidProtocolBufferNanoException.recursionLimitExceeded(); |
||||||
|
} |
||||||
|
final int oldLimit = pushLimit(length); |
||||||
|
++recursionDepth; |
||||||
|
msg.mergeFrom(this); |
||||||
|
checkLastTagWas(0); |
||||||
|
--recursionDepth; |
||||||
|
popLimit(oldLimit); |
||||||
|
} |
||||||
|
|
||||||
|
/** Read a {@code bytes} field value from the stream. */ |
||||||
|
public byte[] readBytes() throws IOException { |
||||||
|
final int size = readRawVarint32(); |
||||||
|
if (size <= (bufferSize - bufferPos) && size > 0) { |
||||||
|
// Fast path: We already have the bytes in a contiguous buffer, so
|
||||||
|
// just copy directly from it.
|
||||||
|
final byte[] result = new byte[size]; |
||||||
|
System.arraycopy(buffer, bufferPos, result, 0, size); |
||||||
|
bufferPos += size; |
||||||
|
return result; |
||||||
|
} else { |
||||||
|
// Slow path: Build a byte array first then copy it.
|
||||||
|
return readRawBytes(size); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** Read a {@code uint32} field value from the stream. */ |
||||||
|
public int readUInt32() throws IOException { |
||||||
|
return readRawVarint32(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Read an enum field value from the stream. Caller is responsible |
||||||
|
* for converting the numeric value to an actual enum. |
||||||
|
*/ |
||||||
|
public int readEnum() throws IOException { |
||||||
|
return readRawVarint32(); |
||||||
|
} |
||||||
|
|
||||||
|
/** Read an {@code sfixed32} field value from the stream. */ |
||||||
|
public int readSFixed32() throws IOException { |
||||||
|
return readRawLittleEndian32(); |
||||||
|
} |
||||||
|
|
||||||
|
/** Read an {@code sfixed64} field value from the stream. */ |
||||||
|
public long readSFixed64() throws IOException { |
||||||
|
return readRawLittleEndian64(); |
||||||
|
} |
||||||
|
|
||||||
|
/** Read an {@code sint32} field value from the stream. */ |
||||||
|
public int readSInt32() throws IOException { |
||||||
|
return decodeZigZag32(readRawVarint32()); |
||||||
|
} |
||||||
|
|
||||||
|
/** Read an {@code sint64} field value from the stream. */ |
||||||
|
public long readSInt64() throws IOException { |
||||||
|
return decodeZigZag64(readRawVarint64()); |
||||||
|
} |
||||||
|
|
||||||
|
// =================================================================
|
||||||
|
|
||||||
|
/** |
||||||
|
* Read a raw Varint from the stream. If larger than 32 bits, discard the |
||||||
|
* upper bits. |
||||||
|
*/ |
||||||
|
public int readRawVarint32() throws IOException { |
||||||
|
byte tmp = readRawByte(); |
||||||
|
if (tmp >= 0) { |
||||||
|
return tmp; |
||||||
|
} |
||||||
|
int result = tmp & 0x7f; |
||||||
|
if ((tmp = readRawByte()) >= 0) { |
||||||
|
result |= tmp << 7; |
||||||
|
} else { |
||||||
|
result |= (tmp & 0x7f) << 7; |
||||||
|
if ((tmp = readRawByte()) >= 0) { |
||||||
|
result |= tmp << 14; |
||||||
|
} else { |
||||||
|
result |= (tmp & 0x7f) << 14; |
||||||
|
if ((tmp = readRawByte()) >= 0) { |
||||||
|
result |= tmp << 21; |
||||||
|
} else { |
||||||
|
result |= (tmp & 0x7f) << 21; |
||||||
|
result |= (tmp = readRawByte()) << 28; |
||||||
|
if (tmp < 0) { |
||||||
|
// Discard upper 32 bits.
|
||||||
|
for (int i = 0; i < 5; i++) { |
||||||
|
if (readRawByte() >= 0) { |
||||||
|
return result; |
||||||
|
} |
||||||
|
} |
||||||
|
throw InvalidProtocolBufferNanoException.malformedVarint(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/** Read a raw Varint from the stream. */ |
||||||
|
public long readRawVarint64() throws IOException { |
||||||
|
int shift = 0; |
||||||
|
long result = 0; |
||||||
|
while (shift < 64) { |
||||||
|
final byte b = readRawByte(); |
||||||
|
result |= (long)(b & 0x7F) << shift; |
||||||
|
if ((b & 0x80) == 0) { |
||||||
|
return result; |
||||||
|
} |
||||||
|
shift += 7; |
||||||
|
} |
||||||
|
throw InvalidProtocolBufferNanoException.malformedVarint(); |
||||||
|
} |
||||||
|
|
||||||
|
/** Read a 32-bit little-endian integer from the stream. */ |
||||||
|
public int readRawLittleEndian32() throws IOException { |
||||||
|
final byte b1 = readRawByte(); |
||||||
|
final byte b2 = readRawByte(); |
||||||
|
final byte b3 = readRawByte(); |
||||||
|
final byte b4 = readRawByte(); |
||||||
|
return ((b1 & 0xff) ) | |
||||||
|
((b2 & 0xff) << 8) | |
||||||
|
((b3 & 0xff) << 16) | |
||||||
|
((b4 & 0xff) << 24); |
||||||
|
} |
||||||
|
|
||||||
|
/** Read a 64-bit little-endian integer from the stream. */ |
||||||
|
public long readRawLittleEndian64() throws IOException { |
||||||
|
final byte b1 = readRawByte(); |
||||||
|
final byte b2 = readRawByte(); |
||||||
|
final byte b3 = readRawByte(); |
||||||
|
final byte b4 = readRawByte(); |
||||||
|
final byte b5 = readRawByte(); |
||||||
|
final byte b6 = readRawByte(); |
||||||
|
final byte b7 = readRawByte(); |
||||||
|
final byte b8 = readRawByte(); |
||||||
|
return (((long)b1 & 0xff) ) | |
||||||
|
(((long)b2 & 0xff) << 8) | |
||||||
|
(((long)b3 & 0xff) << 16) | |
||||||
|
(((long)b4 & 0xff) << 24) | |
||||||
|
(((long)b5 & 0xff) << 32) | |
||||||
|
(((long)b6 & 0xff) << 40) | |
||||||
|
(((long)b7 & 0xff) << 48) | |
||||||
|
(((long)b8 & 0xff) << 56); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers |
||||||
|
* into values that can be efficiently encoded with varint. (Otherwise, |
||||||
|
* negative values must be sign-extended to 64 bits to be varint encoded, |
||||||
|
* thus always taking 10 bytes on the wire.) |
||||||
|
* |
||||||
|
* @param n An unsigned 32-bit integer, stored in a signed int because |
||||||
|
* Java has no explicit unsigned support. |
||||||
|
* @return A signed 32-bit integer. |
||||||
|
*/ |
||||||
|
public static int decodeZigZag32(final int n) { |
||||||
|
return (n >>> 1) ^ -(n & 1); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers |
||||||
|
* into values that can be efficiently encoded with varint. (Otherwise, |
||||||
|
* negative values must be sign-extended to 64 bits to be varint encoded, |
||||||
|
* thus always taking 10 bytes on the wire.) |
||||||
|
* |
||||||
|
* @param n An unsigned 64-bit integer, stored in a signed int because |
||||||
|
* Java has no explicit unsigned support. |
||||||
|
* @return A signed 64-bit integer. |
||||||
|
*/ |
||||||
|
public static long decodeZigZag64(final long n) { |
||||||
|
return (n >>> 1) ^ -(n & 1); |
||||||
|
} |
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
private final byte[] buffer; |
||||||
|
private int bufferStart; |
||||||
|
private int bufferSize; |
||||||
|
private int bufferSizeAfterLimit; |
||||||
|
private int bufferPos; |
||||||
|
private int lastTag; |
||||||
|
|
||||||
|
/** The absolute position of the end of the current message. */ |
||||||
|
private int currentLimit = Integer.MAX_VALUE; |
||||||
|
|
||||||
|
/** See setRecursionLimit() */ |
||||||
|
private int recursionDepth; |
||||||
|
private int recursionLimit = DEFAULT_RECURSION_LIMIT; |
||||||
|
|
||||||
|
/** See setSizeLimit() */ |
||||||
|
private int sizeLimit = DEFAULT_SIZE_LIMIT; |
||||||
|
|
||||||
|
private static final int DEFAULT_RECURSION_LIMIT = 64; |
||||||
|
private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB
|
||||||
|
|
||||||
|
private CodedInputByteBufferNano(final byte[] buffer, final int off, final int len) { |
||||||
|
this.buffer = buffer; |
||||||
|
bufferStart = off; |
||||||
|
bufferSize = off + len; |
||||||
|
bufferPos = off; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the maximum message recursion depth. In order to prevent malicious |
||||||
|
* messages from causing stack overflows, {@code CodedInputStream} limits |
||||||
|
* how deeply messages may be nested. The default limit is 64. |
||||||
|
* |
||||||
|
* @return the old limit. |
||||||
|
*/ |
||||||
|
public int setRecursionLimit(final int limit) { |
||||||
|
if (limit < 0) { |
||||||
|
throw new IllegalArgumentException( |
||||||
|
"Recursion limit cannot be negative: " + limit); |
||||||
|
} |
||||||
|
final int oldLimit = recursionLimit; |
||||||
|
recursionLimit = limit; |
||||||
|
return oldLimit; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the maximum message size. In order to prevent malicious |
||||||
|
* messages from exhausting memory or causing integer overflows, |
||||||
|
* {@code CodedInputStream} limits how large a message may be. |
||||||
|
* The default limit is 64MB. You should set this limit as small |
||||||
|
* as you can without harming your app's functionality. Note that |
||||||
|
* size limits only apply when reading from an {@code InputStream}, not |
||||||
|
* when constructed around a raw byte array. |
||||||
|
* <p> |
||||||
|
* If you want to read several messages from a single CodedInputStream, you |
||||||
|
* could call {@link #resetSizeCounter()} after each one to avoid hitting the |
||||||
|
* size limit. |
||||||
|
* |
||||||
|
* @return the old limit. |
||||||
|
*/ |
||||||
|
public int setSizeLimit(final int limit) { |
||||||
|
if (limit < 0) { |
||||||
|
throw new IllegalArgumentException( |
||||||
|
"Size limit cannot be negative: " + limit); |
||||||
|
} |
||||||
|
final int oldLimit = sizeLimit; |
||||||
|
sizeLimit = limit; |
||||||
|
return oldLimit; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Resets the current size counter to zero (see {@link #setSizeLimit(int)}). |
||||||
|
*/ |
||||||
|
public void resetSizeCounter() { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets {@code currentLimit} to (current position) + {@code byteLimit}. This |
||||||
|
* is called when descending into a length-delimited embedded message. |
||||||
|
* |
||||||
|
* @return the old limit. |
||||||
|
*/ |
||||||
|
public int pushLimit(int byteLimit) throws InvalidProtocolBufferNanoException { |
||||||
|
if (byteLimit < 0) { |
||||||
|
throw InvalidProtocolBufferNanoException.negativeSize(); |
||||||
|
} |
||||||
|
byteLimit += bufferPos; |
||||||
|
final int oldLimit = currentLimit; |
||||||
|
if (byteLimit > oldLimit) { |
||||||
|
throw InvalidProtocolBufferNanoException.truncatedMessage(); |
||||||
|
} |
||||||
|
currentLimit = byteLimit; |
||||||
|
|
||||||
|
recomputeBufferSizeAfterLimit(); |
||||||
|
|
||||||
|
return oldLimit; |
||||||
|
} |
||||||
|
|
||||||
|
private void recomputeBufferSizeAfterLimit() { |
||||||
|
bufferSize += bufferSizeAfterLimit; |
||||||
|
final int bufferEnd = bufferSize; |
||||||
|
if (bufferEnd > currentLimit) { |
||||||
|
// Limit is in current buffer.
|
||||||
|
bufferSizeAfterLimit = bufferEnd - currentLimit; |
||||||
|
bufferSize -= bufferSizeAfterLimit; |
||||||
|
} else { |
||||||
|
bufferSizeAfterLimit = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Discards the current limit, returning to the previous limit. |
||||||
|
* |
||||||
|
* @param oldLimit The old limit, as returned by {@code pushLimit}. |
||||||
|
*/ |
||||||
|
public void popLimit(final int oldLimit) { |
||||||
|
currentLimit = oldLimit; |
||||||
|
recomputeBufferSizeAfterLimit(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the number of bytes to be read before the current limit. |
||||||
|
* If no limit is set, returns -1. |
||||||
|
*/ |
||||||
|
public int getBytesUntilLimit() { |
||||||
|
if (currentLimit == Integer.MAX_VALUE) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
final int currentAbsolutePosition = bufferPos; |
||||||
|
return currentLimit - currentAbsolutePosition; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns true if the stream has reached the end of the input. This is the |
||||||
|
* case if either the end of the underlying input source has been reached or |
||||||
|
* if the stream has reached a limit created using {@link #pushLimit(int)}. |
||||||
|
*/ |
||||||
|
public boolean isAtEnd() { |
||||||
|
return bufferPos == bufferSize; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get current position in buffer relative to beginning offset. |
||||||
|
*/ |
||||||
|
public int getPosition() { |
||||||
|
return bufferPos - bufferStart; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Rewind to previous position. Cannot go forward. |
||||||
|
*/ |
||||||
|
public void rewindToPosition(int position) { |
||||||
|
if (position > bufferPos - bufferStart) { |
||||||
|
throw new IllegalArgumentException( |
||||||
|
"Position " + position + " is beyond current " + (bufferPos - bufferStart)); |
||||||
|
} |
||||||
|
if (position < 0) { |
||||||
|
throw new IllegalArgumentException("Bad position " + position); |
||||||
|
} |
||||||
|
bufferPos = bufferStart + position; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Read one byte from the input. |
||||||
|
* |
||||||
|
* @throws InvalidProtocolBufferNanoException The end of the stream or the current |
||||||
|
* limit was reached. |
||||||
|
*/ |
||||||
|
public byte readRawByte() throws IOException { |
||||||
|
if (bufferPos == bufferSize) { |
||||||
|
throw InvalidProtocolBufferNanoException.truncatedMessage(); |
||||||
|
} |
||||||
|
return buffer[bufferPos++]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Read a fixed size of bytes from the input. |
||||||
|
* |
||||||
|
* @throws InvalidProtocolBufferNanoException The end of the stream or the current |
||||||
|
* limit was reached. |
||||||
|
*/ |
||||||
|
public byte[] readRawBytes(final int size) throws IOException { |
||||||
|
if (size < 0) { |
||||||
|
throw InvalidProtocolBufferNanoException.negativeSize(); |
||||||
|
} |
||||||
|
|
||||||
|
if (bufferPos + size > currentLimit) { |
||||||
|
// Read to the end of the stream anyway.
|
||||||
|
skipRawBytes(currentLimit - bufferPos); |
||||||
|
// Then fail.
|
||||||
|
throw InvalidProtocolBufferNanoException.truncatedMessage(); |
||||||
|
} |
||||||
|
|
||||||
|
if (size <= bufferSize - bufferPos) { |
||||||
|
// We have all the bytes we need already.
|
||||||
|
final byte[] bytes = new byte[size]; |
||||||
|
System.arraycopy(buffer, bufferPos, bytes, 0, size); |
||||||
|
bufferPos += size; |
||||||
|
return bytes; |
||||||
|
} else { |
||||||
|
throw InvalidProtocolBufferNanoException.truncatedMessage(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Reads and discards {@code size} bytes. |
||||||
|
* |
||||||
|
* @throws InvalidProtocolBufferNanoException The end of the stream or the current |
||||||
|
* limit was reached. |
||||||
|
*/ |
||||||
|
public void skipRawBytes(final int size) throws IOException { |
||||||
|
if (size < 0) { |
||||||
|
throw InvalidProtocolBufferNanoException.negativeSize(); |
||||||
|
} |
||||||
|
|
||||||
|
if (bufferPos + size > currentLimit) { |
||||||
|
// Read to the end of the stream anyway.
|
||||||
|
skipRawBytes(currentLimit - bufferPos); |
||||||
|
// Then fail.
|
||||||
|
throw InvalidProtocolBufferNanoException.truncatedMessage(); |
||||||
|
} |
||||||
|
|
||||||
|
if (size <= bufferSize - bufferPos) { |
||||||
|
// We have all the bytes we need already.
|
||||||
|
bufferPos += size; |
||||||
|
} else { |
||||||
|
throw InvalidProtocolBufferNanoException.truncatedMessage(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,910 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2013 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
package com.google.protobuf.nano; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.io.UnsupportedEncodingException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Encodes and writes protocol message fields. |
||||||
|
* |
||||||
|
* <p>This class contains two kinds of methods: methods that write specific |
||||||
|
* protocol message constructs and field types (e.g. {@link #writeTag} and |
||||||
|
* {@link #writeInt32}) and methods that write low-level values (e.g. |
||||||
|
* {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are |
||||||
|
* writing encoded protocol messages, you should use the former methods, but if |
||||||
|
* you are writing some other format of your own design, use the latter. |
||||||
|
* |
||||||
|
* <p>This class is totally unsynchronized. |
||||||
|
* |
||||||
|
* @author kneton@google.com Kenton Varda |
||||||
|
*/ |
||||||
|
public final class CodedOutputByteBufferNano { |
||||||
|
private final byte[] buffer; |
||||||
|
private final int limit; |
||||||
|
private int position; |
||||||
|
|
||||||
|
private CodedOutputByteBufferNano(final byte[] buffer, final int offset, |
||||||
|
final int length) { |
||||||
|
this.buffer = buffer; |
||||||
|
position = offset; |
||||||
|
limit = offset + length; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new {@code CodedOutputStream} that writes directly to the given |
||||||
|
* byte array. If more bytes are written than fit in the array, |
||||||
|
* {@link OutOfSpaceException} will be thrown. Writing directly to a flat |
||||||
|
* array is faster than writing to an {@code OutputStream}. |
||||||
|
*/ |
||||||
|
public static CodedOutputByteBufferNano newInstance(final byte[] flatArray) { |
||||||
|
return newInstance(flatArray, 0, flatArray.length); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new {@code CodedOutputStream} that writes directly to the given |
||||||
|
* byte array slice. If more bytes are written than fit in the slice, |
||||||
|
* {@link OutOfSpaceException} will be thrown. Writing directly to a flat |
||||||
|
* array is faster than writing to an {@code OutputStream}. |
||||||
|
*/ |
||||||
|
public static CodedOutputByteBufferNano newInstance(final byte[] flatArray, |
||||||
|
final int offset, |
||||||
|
final int length) { |
||||||
|
return new CodedOutputByteBufferNano(flatArray, offset, length); |
||||||
|
} |
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Write a {@code double} field, including tag, to the stream. */ |
||||||
|
public void writeDouble(final int fieldNumber, final double value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); |
||||||
|
writeDoubleNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code float} field, including tag, to the stream. */ |
||||||
|
public void writeFloat(final int fieldNumber, final float value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); |
||||||
|
writeFloatNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code uint64} field, including tag, to the stream. */ |
||||||
|
public void writeUInt64(final int fieldNumber, final long value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); |
||||||
|
writeUInt64NoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an {@code int64} field, including tag, to the stream. */ |
||||||
|
public void writeInt64(final int fieldNumber, final long value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); |
||||||
|
writeInt64NoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an {@code int32} field, including tag, to the stream. */ |
||||||
|
public void writeInt32(final int fieldNumber, final int value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); |
||||||
|
writeInt32NoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code fixed64} field, including tag, to the stream. */ |
||||||
|
public void writeFixed64(final int fieldNumber, final long value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); |
||||||
|
writeFixed64NoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code fixed32} field, including tag, to the stream. */ |
||||||
|
public void writeFixed32(final int fieldNumber, final int value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); |
||||||
|
writeFixed32NoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code bool} field, including tag, to the stream. */ |
||||||
|
public void writeBool(final int fieldNumber, final boolean value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); |
||||||
|
writeBoolNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code string} field, including tag, to the stream. */ |
||||||
|
public void writeString(final int fieldNumber, final String value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); |
||||||
|
writeStringNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code group} field, including tag, to the stream. */ |
||||||
|
public void writeGroup(final int fieldNumber, final MessageNano value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_START_GROUP); |
||||||
|
writeGroupNoTag(value); |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an embedded message field, including tag, to the stream. */ |
||||||
|
public void writeMessage(final int fieldNumber, final MessageNano value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); |
||||||
|
writeMessageNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code bytes} field, including tag, to the stream. */ |
||||||
|
public void writeBytes(final int fieldNumber, final byte[] value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); |
||||||
|
writeBytesNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code byte} field, including tag, to the stream. */ |
||||||
|
public void writeByteArray(final int fieldNumber, final byte[] value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); |
||||||
|
writeByteArrayNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Write a {@code uint32} field, including tag, to the stream. */ |
||||||
|
public void writeUInt32(final int fieldNumber, final int value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); |
||||||
|
writeUInt32NoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Write an enum field, including tag, to the stream. Caller is responsible |
||||||
|
* for converting the enum value to its numeric value. |
||||||
|
*/ |
||||||
|
public void writeEnum(final int fieldNumber, final int value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); |
||||||
|
writeEnumNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an {@code sfixed32} field, including tag, to the stream. */ |
||||||
|
public void writeSFixed32(final int fieldNumber, final int value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); |
||||||
|
writeSFixed32NoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an {@code sfixed64} field, including tag, to the stream. */ |
||||||
|
public void writeSFixed64(final int fieldNumber, final long value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); |
||||||
|
writeSFixed64NoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an {@code sint32} field, including tag, to the stream. */ |
||||||
|
public void writeSInt32(final int fieldNumber, final int value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); |
||||||
|
writeSInt32NoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an {@code sint64} field, including tag, to the stream. */ |
||||||
|
public void writeSInt64(final int fieldNumber, final long value) |
||||||
|
throws IOException { |
||||||
|
writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); |
||||||
|
writeSInt64NoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Write a MessageSet extension field to the stream. For historical reasons, |
||||||
|
* the wire format differs from normal fields. |
||||||
|
*/ |
||||||
|
// public void writeMessageSetExtension(final int fieldNumber,
|
||||||
|
// final MessageMicro value)
|
||||||
|
// throws IOException {
|
||||||
|
// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
|
||||||
|
// writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
|
||||||
|
// writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
|
||||||
|
// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
|
||||||
|
// }
|
||||||
|
|
||||||
|
/** |
||||||
|
* Write an unparsed MessageSet extension field to the stream. For |
||||||
|
* historical reasons, the wire format differs from normal fields. |
||||||
|
*/ |
||||||
|
// public void writeRawMessageSetExtension(final int fieldNumber,
|
||||||
|
// final ByteStringMicro value)
|
||||||
|
// throws IOException {
|
||||||
|
// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
|
||||||
|
// writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
|
||||||
|
// writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
|
||||||
|
// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Write a {@code double} field to the stream. */ |
||||||
|
public void writeDoubleNoTag(final double value) throws IOException { |
||||||
|
writeRawLittleEndian64(Double.doubleToLongBits(value)); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code float} field to the stream. */ |
||||||
|
public void writeFloatNoTag(final float value) throws IOException { |
||||||
|
writeRawLittleEndian32(Float.floatToIntBits(value)); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code uint64} field to the stream. */ |
||||||
|
public void writeUInt64NoTag(final long value) throws IOException { |
||||||
|
writeRawVarint64(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an {@code int64} field to the stream. */ |
||||||
|
public void writeInt64NoTag(final long value) throws IOException { |
||||||
|
writeRawVarint64(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an {@code int32} field to the stream. */ |
||||||
|
public void writeInt32NoTag(final int value) throws IOException { |
||||||
|
if (value >= 0) { |
||||||
|
writeRawVarint32(value); |
||||||
|
} else { |
||||||
|
// Must sign-extend.
|
||||||
|
writeRawVarint64(value); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code fixed64} field to the stream. */ |
||||||
|
public void writeFixed64NoTag(final long value) throws IOException { |
||||||
|
writeRawLittleEndian64(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code fixed32} field to the stream. */ |
||||||
|
public void writeFixed32NoTag(final int value) throws IOException { |
||||||
|
writeRawLittleEndian32(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code bool} field to the stream. */ |
||||||
|
public void writeBoolNoTag(final boolean value) throws IOException { |
||||||
|
writeRawByte(value ? 1 : 0); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code string} field to the stream. */ |
||||||
|
public void writeStringNoTag(final String value) throws IOException { |
||||||
|
// Unfortunately there does not appear to be any way to tell Java to encode
|
||||||
|
// UTF-8 directly into our buffer, so we have to let it create its own byte
|
||||||
|
// array and then copy.
|
||||||
|
final byte[] bytes = value.getBytes("UTF-8"); |
||||||
|
writeRawVarint32(bytes.length); |
||||||
|
writeRawBytes(bytes); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code group} field to the stream. */ |
||||||
|
public void writeGroupNoTag(final MessageNano value) throws IOException { |
||||||
|
value.writeTo(this); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an embedded message field to the stream. */ |
||||||
|
public void writeMessageNoTag(final MessageNano value) throws IOException { |
||||||
|
writeRawVarint32(value.getCachedSize()); |
||||||
|
value.writeTo(this); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code bytes} field to the stream. */ |
||||||
|
public void writeBytesNoTag(final byte[] value) throws IOException { |
||||||
|
writeRawVarint32(value.length); |
||||||
|
writeRawBytes(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code byte[]} field to the stream. */ |
||||||
|
public void writeByteArrayNoTag(final byte [] value) throws IOException { |
||||||
|
writeRawVarint32(value.length); |
||||||
|
writeRawBytes(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a {@code uint32} field to the stream. */ |
||||||
|
public void writeUInt32NoTag(final int value) throws IOException { |
||||||
|
writeRawVarint32(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Write an enum field to the stream. Caller is responsible |
||||||
|
* for converting the enum value to its numeric value. |
||||||
|
*/ |
||||||
|
public void writeEnumNoTag(final int value) throws IOException { |
||||||
|
writeRawVarint32(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an {@code sfixed32} field to the stream. */ |
||||||
|
public void writeSFixed32NoTag(final int value) throws IOException { |
||||||
|
writeRawLittleEndian32(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an {@code sfixed64} field to the stream. */ |
||||||
|
public void writeSFixed64NoTag(final long value) throws IOException { |
||||||
|
writeRawLittleEndian64(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an {@code sint32} field to the stream. */ |
||||||
|
public void writeSInt32NoTag(final int value) throws IOException { |
||||||
|
writeRawVarint32(encodeZigZag32(value)); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an {@code sint64} field to the stream. */ |
||||||
|
public void writeSInt64NoTag(final long value) throws IOException { |
||||||
|
writeRawVarint64(encodeZigZag64(value)); |
||||||
|
} |
||||||
|
|
||||||
|
// =================================================================
|
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code double} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeDoubleSize(final int fieldNumber, |
||||||
|
final double value) { |
||||||
|
return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code float} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeFloatSize(final int fieldNumber, final float value) { |
||||||
|
return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code uint64} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeUInt64Size(final int fieldNumber, final long value) { |
||||||
|
return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* {@code int64} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeInt64Size(final int fieldNumber, final long value) { |
||||||
|
return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* {@code int32} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeInt32Size(final int fieldNumber, final int value) { |
||||||
|
return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code fixed64} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeFixed64Size(final int fieldNumber, |
||||||
|
final long value) { |
||||||
|
return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code fixed32} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeFixed32Size(final int fieldNumber, |
||||||
|
final int value) { |
||||||
|
return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code bool} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeBoolSize(final int fieldNumber, |
||||||
|
final boolean value) { |
||||||
|
return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code string} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeStringSize(final int fieldNumber, |
||||||
|
final String value) { |
||||||
|
return computeTagSize(fieldNumber) + computeStringSizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code group} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeGroupSize(final int fieldNumber, |
||||||
|
final MessageNano value) { |
||||||
|
return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* embedded message field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeMessageSize(final int fieldNumber, |
||||||
|
final MessageNano value) { |
||||||
|
return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code bytes} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeBytesSize(final int fieldNumber, |
||||||
|
final byte[] value) { |
||||||
|
return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code byte[]} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeByteArraySize(final int fieldNumber, |
||||||
|
final byte[] value) { |
||||||
|
return computeTagSize(fieldNumber) + computeByteArraySizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code uint32} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeUInt32Size(final int fieldNumber, final int value) { |
||||||
|
return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* enum field, including tag. Caller is responsible for converting the |
||||||
|
* enum value to its numeric value. |
||||||
|
*/ |
||||||
|
public static int computeEnumSize(final int fieldNumber, final int value) { |
||||||
|
return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* {@code sfixed32} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeSFixed32Size(final int fieldNumber, |
||||||
|
final int value) { |
||||||
|
return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* {@code sfixed64} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeSFixed64Size(final int fieldNumber, |
||||||
|
final long value) { |
||||||
|
return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* {@code sint32} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeSInt32Size(final int fieldNumber, final int value) { |
||||||
|
return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* {@code sint64} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeSInt64Size(final int fieldNumber, final long value) { |
||||||
|
return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* MessageSet extension to the stream. For historical reasons, |
||||||
|
* the wire format differs from normal fields. |
||||||
|
*/ |
||||||
|
// public static int computeMessageSetExtensionSize(
|
||||||
|
// final int fieldNumber, final MessageMicro value) {
|
||||||
|
// return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
|
||||||
|
// computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
|
||||||
|
// computeMessageSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
|
||||||
|
// }
|
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* unparsed MessageSet extension field to the stream. For |
||||||
|
* historical reasons, the wire format differs from normal fields. |
||||||
|
*/ |
||||||
|
// public static int computeRawMessageSetExtensionSize(
|
||||||
|
// final int fieldNumber, final ByteStringMicro value) {
|
||||||
|
// return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
|
||||||
|
// computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
|
||||||
|
// computeBytesSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code double} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeDoubleSizeNoTag(final double value) { |
||||||
|
return LITTLE_ENDIAN_64_SIZE; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code float} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeFloatSizeNoTag(final float value) { |
||||||
|
return LITTLE_ENDIAN_32_SIZE; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code uint64} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeUInt64SizeNoTag(final long value) { |
||||||
|
return computeRawVarint64Size(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* {@code int64} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeInt64SizeNoTag(final long value) { |
||||||
|
return computeRawVarint64Size(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* {@code int32} field, including tag. |
||||||
|
*/ |
||||||
|
public static int computeInt32SizeNoTag(final int value) { |
||||||
|
if (value >= 0) { |
||||||
|
return computeRawVarint32Size(value); |
||||||
|
} else { |
||||||
|
// Must sign-extend.
|
||||||
|
return 10; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code fixed64} field. |
||||||
|
*/ |
||||||
|
public static int computeFixed64SizeNoTag(final long value) { |
||||||
|
return LITTLE_ENDIAN_64_SIZE; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code fixed32} field. |
||||||
|
*/ |
||||||
|
public static int computeFixed32SizeNoTag(final int value) { |
||||||
|
return LITTLE_ENDIAN_32_SIZE; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code bool} field. |
||||||
|
*/ |
||||||
|
public static int computeBoolSizeNoTag(final boolean value) { |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code string} field. |
||||||
|
*/ |
||||||
|
public static int computeStringSizeNoTag(final String value) { |
||||||
|
try { |
||||||
|
final byte[] bytes = value.getBytes("UTF-8"); |
||||||
|
return computeRawVarint32Size(bytes.length) + |
||||||
|
bytes.length; |
||||||
|
} catch (UnsupportedEncodingException e) { |
||||||
|
throw new RuntimeException("UTF-8 not supported."); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code group} field. |
||||||
|
*/ |
||||||
|
public static int computeGroupSizeNoTag(final MessageNano value) { |
||||||
|
return value.getSerializedSize(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an embedded |
||||||
|
* message field. |
||||||
|
*/ |
||||||
|
public static int computeMessageSizeNoTag(final MessageNano value) { |
||||||
|
final int size = value.getSerializedSize(); |
||||||
|
return computeRawVarint32Size(size) + size; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code bytes} field. |
||||||
|
*/ |
||||||
|
public static int computeBytesSizeNoTag(final byte[] value) { |
||||||
|
return computeRawVarint32Size(value.length) + value.length; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code byte[]} field. |
||||||
|
*/ |
||||||
|
public static int computeByteArraySizeNoTag(final byte[] value) { |
||||||
|
return computeRawVarint32Size(value.length) + value.length; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a |
||||||
|
* {@code uint32} field. |
||||||
|
*/ |
||||||
|
public static int computeUInt32SizeNoTag(final int value) { |
||||||
|
return computeRawVarint32Size(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an enum field. |
||||||
|
* Caller is responsible for converting the enum value to its numeric value. |
||||||
|
*/ |
||||||
|
public static int computeEnumSizeNoTag(final int value) { |
||||||
|
return computeRawVarint32Size(value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* {@code sfixed32} field. |
||||||
|
*/ |
||||||
|
public static int computeSFixed32SizeNoTag(final int value) { |
||||||
|
return LITTLE_ENDIAN_32_SIZE; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* {@code sfixed64} field. |
||||||
|
*/ |
||||||
|
public static int computeSFixed64SizeNoTag(final long value) { |
||||||
|
return LITTLE_ENDIAN_64_SIZE; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* {@code sint32} field. |
||||||
|
*/ |
||||||
|
public static int computeSInt32SizeNoTag(final int value) { |
||||||
|
return computeRawVarint32Size(encodeZigZag32(value)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode an |
||||||
|
* {@code sint64} field. |
||||||
|
*/ |
||||||
|
public static int computeSInt64SizeNoTag(final long value) { |
||||||
|
return computeRawVarint64Size(encodeZigZag64(value)); |
||||||
|
} |
||||||
|
|
||||||
|
// =================================================================
|
||||||
|
|
||||||
|
/** |
||||||
|
* If writing to a flat array, return the space left in the array. |
||||||
|
* Otherwise, throws {@code UnsupportedOperationException}. |
||||||
|
*/ |
||||||
|
public int spaceLeft() { |
||||||
|
return limit - position; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Verifies that {@link #spaceLeft()} returns zero. It's common to create |
||||||
|
* a byte array that is exactly big enough to hold a message, then write to |
||||||
|
* it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()} |
||||||
|
* after writing verifies that the message was actually as big as expected, |
||||||
|
* which can help catch bugs. |
||||||
|
*/ |
||||||
|
public void checkNoSpaceLeft() { |
||||||
|
if (spaceLeft() != 0) { |
||||||
|
throw new IllegalStateException( |
||||||
|
"Did not write as much data as expected."); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* If you create a CodedOutputStream around a simple flat array, you must |
||||||
|
* not attempt to write more bytes than the array has space. Otherwise, |
||||||
|
* this exception will be thrown. |
||||||
|
*/ |
||||||
|
public static class OutOfSpaceException extends IOException { |
||||||
|
private static final long serialVersionUID = -6947486886997889499L; |
||||||
|
|
||||||
|
OutOfSpaceException(int position, int limit) { |
||||||
|
super("CodedOutputStream was writing to a flat byte array and ran " + |
||||||
|
"out of space (pos " + position + " limit " + limit + ")."); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a single byte. */ |
||||||
|
public void writeRawByte(final byte value) throws IOException { |
||||||
|
if (position == limit) { |
||||||
|
// We're writing to a single buffer.
|
||||||
|
throw new OutOfSpaceException(position, limit); |
||||||
|
} |
||||||
|
|
||||||
|
buffer[position++] = value; |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a single byte, represented by an integer value. */ |
||||||
|
public void writeRawByte(final int value) throws IOException { |
||||||
|
writeRawByte((byte) value); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an array of bytes. */ |
||||||
|
public void writeRawBytes(final byte[] value) throws IOException { |
||||||
|
writeRawBytes(value, 0, value.length); |
||||||
|
} |
||||||
|
|
||||||
|
/** Write part of an array of bytes. */ |
||||||
|
public void writeRawBytes(final byte[] value, int offset, int length) |
||||||
|
throws IOException { |
||||||
|
if (limit - position >= length) { |
||||||
|
// We have room in the current buffer.
|
||||||
|
System.arraycopy(value, offset, buffer, position, length); |
||||||
|
position += length; |
||||||
|
} else { |
||||||
|
// We're writing to a single buffer.
|
||||||
|
throw new OutOfSpaceException(position, limit); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** Encode and write a tag. */ |
||||||
|
public void writeTag(final int fieldNumber, final int wireType) |
||||||
|
throws IOException { |
||||||
|
writeRawVarint32(WireFormatNano.makeTag(fieldNumber, wireType)); |
||||||
|
} |
||||||
|
|
||||||
|
/** Compute the number of bytes that would be needed to encode a tag. */ |
||||||
|
public static int computeTagSize(final int fieldNumber) { |
||||||
|
return computeRawVarint32Size(WireFormatNano.makeTag(fieldNumber, 0)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Encode and write a varint. {@code value} is treated as |
||||||
|
* unsigned, so it won't be sign-extended if negative. |
||||||
|
*/ |
||||||
|
public void writeRawVarint32(int value) throws IOException { |
||||||
|
while (true) { |
||||||
|
if ((value & ~0x7F) == 0) { |
||||||
|
writeRawByte(value); |
||||||
|
return; |
||||||
|
} else { |
||||||
|
writeRawByte((value & 0x7F) | 0x80); |
||||||
|
value >>>= 7; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Compute the number of bytes that would be needed to encode a varint. |
||||||
|
* {@code value} is treated as unsigned, so it won't be sign-extended if |
||||||
|
* negative. |
||||||
|
*/ |
||||||
|
public static int computeRawVarint32Size(final int value) { |
||||||
|
if ((value & (0xffffffff << 7)) == 0) return 1; |
||||||
|
if ((value & (0xffffffff << 14)) == 0) return 2; |
||||||
|
if ((value & (0xffffffff << 21)) == 0) return 3; |
||||||
|
if ((value & (0xffffffff << 28)) == 0) return 4; |
||||||
|
return 5; |
||||||
|
} |
||||||
|
|
||||||
|
/** Encode and write a varint. */ |
||||||
|
public void writeRawVarint64(long value) throws IOException { |
||||||
|
while (true) { |
||||||
|
if ((value & ~0x7FL) == 0) { |
||||||
|
writeRawByte((int)value); |
||||||
|
return; |
||||||
|
} else { |
||||||
|
writeRawByte(((int)value & 0x7F) | 0x80); |
||||||
|
value >>>= 7; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** Compute the number of bytes that would be needed to encode a varint. */ |
||||||
|
public static int computeRawVarint64Size(final long value) { |
||||||
|
if ((value & (0xffffffffffffffffL << 7)) == 0) return 1; |
||||||
|
if ((value & (0xffffffffffffffffL << 14)) == 0) return 2; |
||||||
|
if ((value & (0xffffffffffffffffL << 21)) == 0) return 3; |
||||||
|
if ((value & (0xffffffffffffffffL << 28)) == 0) return 4; |
||||||
|
if ((value & (0xffffffffffffffffL << 35)) == 0) return 5; |
||||||
|
if ((value & (0xffffffffffffffffL << 42)) == 0) return 6; |
||||||
|
if ((value & (0xffffffffffffffffL << 49)) == 0) return 7; |
||||||
|
if ((value & (0xffffffffffffffffL << 56)) == 0) return 8; |
||||||
|
if ((value & (0xffffffffffffffffL << 63)) == 0) return 9; |
||||||
|
return 10; |
||||||
|
} |
||||||
|
|
||||||
|
/** Write a little-endian 32-bit integer. */ |
||||||
|
public void writeRawLittleEndian32(final int value) throws IOException { |
||||||
|
writeRawByte((value ) & 0xFF); |
||||||
|
writeRawByte((value >> 8) & 0xFF); |
||||||
|
writeRawByte((value >> 16) & 0xFF); |
||||||
|
writeRawByte((value >> 24) & 0xFF); |
||||||
|
} |
||||||
|
|
||||||
|
public static final int LITTLE_ENDIAN_32_SIZE = 4; |
||||||
|
|
||||||
|
/** Write a little-endian 64-bit integer. */ |
||||||
|
public void writeRawLittleEndian64(final long value) throws IOException { |
||||||
|
writeRawByte((int)(value ) & 0xFF); |
||||||
|
writeRawByte((int)(value >> 8) & 0xFF); |
||||||
|
writeRawByte((int)(value >> 16) & 0xFF); |
||||||
|
writeRawByte((int)(value >> 24) & 0xFF); |
||||||
|
writeRawByte((int)(value >> 32) & 0xFF); |
||||||
|
writeRawByte((int)(value >> 40) & 0xFF); |
||||||
|
writeRawByte((int)(value >> 48) & 0xFF); |
||||||
|
writeRawByte((int)(value >> 56) & 0xFF); |
||||||
|
} |
||||||
|
|
||||||
|
public static final int LITTLE_ENDIAN_64_SIZE = 8; |
||||||
|
|
||||||
|
/** |
||||||
|
* Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers |
||||||
|
* into values that can be efficiently encoded with varint. (Otherwise, |
||||||
|
* negative values must be sign-extended to 64 bits to be varint encoded, |
||||||
|
* thus always taking 10 bytes on the wire.) |
||||||
|
* |
||||||
|
* @param n A signed 32-bit integer. |
||||||
|
* @return An unsigned 32-bit integer, stored in a signed int because |
||||||
|
* Java has no explicit unsigned support. |
||||||
|
*/ |
||||||
|
public static int encodeZigZag32(final int n) { |
||||||
|
// Note: the right-shift must be arithmetic
|
||||||
|
return (n << 1) ^ (n >> 31); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers |
||||||
|
* into values that can be efficiently encoded with varint. (Otherwise, |
||||||
|
* negative values must be sign-extended to 64 bits to be varint encoded, |
||||||
|
* thus always taking 10 bytes on the wire.) |
||||||
|
* |
||||||
|
* @param n A signed 64-bit integer. |
||||||
|
* @return An unsigned 64-bit integer, stored in a signed int because |
||||||
|
* Java has no explicit unsigned support. |
||||||
|
*/ |
||||||
|
public static long encodeZigZag64(final long n) { |
||||||
|
// Note: the right-shift must be arithmetic
|
||||||
|
return (n << 1) ^ (n >> 63); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,113 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
package com.google.protobuf.nano; |
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException; |
||||||
|
|
||||||
|
/** |
||||||
|
* The classes contained within are used internally by the Protocol Buffer |
||||||
|
* library and generated message implementations. They are public only because |
||||||
|
* those generated messages do not reside in the {@code protobuf} package. |
||||||
|
* Others should not use this class directly. |
||||||
|
* |
||||||
|
* @author kenton@google.com (Kenton Varda) |
||||||
|
*/ |
||||||
|
public class InternalNano { |
||||||
|
/** |
||||||
|
* Helper called by generated code to construct default values for string |
||||||
|
* fields. |
||||||
|
* <p> |
||||||
|
* The protocol compiler does not actually contain a UTF-8 decoder -- it |
||||||
|
* just pushes UTF-8-encoded text around without touching it. The one place |
||||||
|
* where this presents a problem is when generating Java string literals. |
||||||
|
* Unicode characters in the string literal would normally need to be encoded |
||||||
|
* using a Unicode escape sequence, which would require decoding them. |
||||||
|
* To get around this, protoc instead embeds the UTF-8 bytes into the |
||||||
|
* generated code and leaves it to the runtime library to decode them. |
||||||
|
* <p> |
||||||
|
* It gets worse, though. If protoc just generated a byte array, like: |
||||||
|
* new byte[] {0x12, 0x34, 0x56, 0x78} |
||||||
|
* Java actually generates *code* which allocates an array and then fills |
||||||
|
* in each value. This is much less efficient than just embedding the bytes |
||||||
|
* directly into the bytecode. To get around this, we need another |
||||||
|
* work-around. String literals are embedded directly, so protoc actually |
||||||
|
* generates a string literal corresponding to the bytes. The easiest way |
||||||
|
* to do this is to use the ISO-8859-1 character set, which corresponds to |
||||||
|
* the first 256 characters of the Unicode range. Protoc can then use |
||||||
|
* good old CEscape to generate the string. |
||||||
|
* <p> |
||||||
|
* So we have a string literal which represents a set of bytes which |
||||||
|
* represents another string. This function -- stringDefaultValue -- |
||||||
|
* converts from the generated string to the string we actually want. The |
||||||
|
* generated code calls this automatically. |
||||||
|
*/ |
||||||
|
public static final String stringDefaultValue(String bytes) { |
||||||
|
try { |
||||||
|
return new String(bytes.getBytes("ISO-8859-1"), "UTF-8"); |
||||||
|
} catch (UnsupportedEncodingException e) { |
||||||
|
// This should never happen since all JVMs are required to implement
|
||||||
|
// both of the above character sets.
|
||||||
|
throw new IllegalStateException( |
||||||
|
"Java VM does not support a standard character set.", e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Helper called by generated code to construct default values for bytes |
||||||
|
* fields. |
||||||
|
* <p> |
||||||
|
* This is a lot like {@link #stringDefaultValue}, but for bytes fields. |
||||||
|
* In this case we only need the second of the two hacks -- allowing us to |
||||||
|
* embed raw bytes as a string literal with ISO-8859-1 encoding. |
||||||
|
*/ |
||||||
|
public static final byte[] bytesDefaultValue(String bytes) { |
||||||
|
try { |
||||||
|
return bytes.getBytes("ISO-8859-1"); |
||||||
|
} catch (UnsupportedEncodingException e) { |
||||||
|
// This should never happen since all JVMs are required to implement
|
||||||
|
// ISO-8859-1.
|
||||||
|
throw new IllegalStateException( |
||||||
|
"Java VM does not support a standard character set.", e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Helper function to convert a string into UTF-8 while turning the |
||||||
|
* UnsupportedEncodingException to a RuntimeException. |
||||||
|
*/ |
||||||
|
public static final byte[] copyFromUtf8(final String text) { |
||||||
|
try { |
||||||
|
return text.getBytes("UTF-8"); |
||||||
|
} catch (UnsupportedEncodingException e) { |
||||||
|
throw new RuntimeException("UTF-8 not supported?"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,93 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2013 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
package com.google.protobuf.nano; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Thrown when a protocol message being parsed is invalid in some way, |
||||||
|
* e.g. it contains a malformed varint or a negative byte length. |
||||||
|
* |
||||||
|
* @author kenton@google.com Kenton Varda |
||||||
|
*/ |
||||||
|
public class InvalidProtocolBufferNanoException extends IOException { |
||||||
|
private static final long serialVersionUID = -1616151763072450476L; |
||||||
|
|
||||||
|
public InvalidProtocolBufferNanoException(final String description) { |
||||||
|
super(description); |
||||||
|
} |
||||||
|
|
||||||
|
static InvalidProtocolBufferNanoException truncatedMessage() { |
||||||
|
return new InvalidProtocolBufferNanoException( |
||||||
|
"While parsing a protocol message, the input ended unexpectedly " + |
||||||
|
"in the middle of a field. This could mean either than the " + |
||||||
|
"input has been truncated or that an embedded message " + |
||||||
|
"misreported its own length."); |
||||||
|
} |
||||||
|
|
||||||
|
static InvalidProtocolBufferNanoException negativeSize() { |
||||||
|
return new InvalidProtocolBufferNanoException( |
||||||
|
"CodedInputStream encountered an embedded string or message " + |
||||||
|
"which claimed to have negative size."); |
||||||
|
} |
||||||
|
|
||||||
|
static InvalidProtocolBufferNanoException malformedVarint() { |
||||||
|
return new InvalidProtocolBufferNanoException( |
||||||
|
"CodedInputStream encountered a malformed varint."); |
||||||
|
} |
||||||
|
|
||||||
|
static InvalidProtocolBufferNanoException invalidTag() { |
||||||
|
return new InvalidProtocolBufferNanoException( |
||||||
|
"Protocol message contained an invalid tag (zero)."); |
||||||
|
} |
||||||
|
|
||||||
|
static InvalidProtocolBufferNanoException invalidEndTag() { |
||||||
|
return new InvalidProtocolBufferNanoException( |
||||||
|
"Protocol message end-group tag did not match expected tag."); |
||||||
|
} |
||||||
|
|
||||||
|
static InvalidProtocolBufferNanoException invalidWireType() { |
||||||
|
return new InvalidProtocolBufferNanoException( |
||||||
|
"Protocol message tag had invalid wire type."); |
||||||
|
} |
||||||
|
|
||||||
|
static InvalidProtocolBufferNanoException recursionLimitExceeded() { |
||||||
|
return new InvalidProtocolBufferNanoException( |
||||||
|
"Protocol message had too many levels of nesting. May be malicious. " + |
||||||
|
"Use CodedInputStream.setRecursionLimit() to increase the depth limit."); |
||||||
|
} |
||||||
|
|
||||||
|
static InvalidProtocolBufferNanoException sizeLimitExceeded() { |
||||||
|
return new InvalidProtocolBufferNanoException( |
||||||
|
"Protocol message was too large. May be malicious. " + |
||||||
|
"Use CodedInputStream.setSizeLimit() to increase the size limit."); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,128 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2013 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
package com.google.protobuf.nano; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Abstract interface implemented by Protocol Message objects. |
||||||
|
* |
||||||
|
* @author wink@google.com Wink Saville |
||||||
|
*/ |
||||||
|
public abstract class MessageNano { |
||||||
|
/** |
||||||
|
* Get the number of bytes required to encode this message. |
||||||
|
* Returns the cached size or calls getSerializedSize which |
||||||
|
* sets the cached size. This is used internally when serializing |
||||||
|
* so the size is only computed once. If a member is modified |
||||||
|
* then this could be stale call getSerializedSize if in doubt. |
||||||
|
*/ |
||||||
|
abstract public int getCachedSize(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Computes the number of bytes required to encode this message. |
||||||
|
* The size is cached and the cached result can be retrieved |
||||||
|
* using getCachedSize(). |
||||||
|
*/ |
||||||
|
abstract public int getSerializedSize(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Serializes the message and writes it to {@code output}. This does not |
||||||
|
* flush or close the stream. |
||||||
|
*/ |
||||||
|
abstract public void writeTo(CodedOutputByteBufferNano output) throws java.io.IOException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Parse {@code input} as a message of this type and merge it with the |
||||||
|
* message being built. |
||||||
|
*/ |
||||||
|
abstract public MessageNano mergeFrom(final CodedInputByteBufferNano input) throws IOException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Serialize to a byte array. |
||||||
|
* @return byte array with the serialized data. |
||||||
|
*/ |
||||||
|
public static final byte[] toByteArray(MessageNano msg) { |
||||||
|
final byte[] result = new byte[msg.getSerializedSize()]; |
||||||
|
toByteArray(msg, result, 0, result.length); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Serialize to a byte array starting at offset through length. The |
||||||
|
* method getSerializedSize must have been called prior to calling |
||||||
|
* this method so the proper length is know. If an attempt to |
||||||
|
* write more than length bytes OutOfSpaceException will be thrown |
||||||
|
* and if length bytes are not written then IllegalStateException |
||||||
|
* is thrown. |
||||||
|
* @return byte array with the serialized data. |
||||||
|
*/ |
||||||
|
public static final void toByteArray(MessageNano msg, byte [] data, int offset, int length) { |
||||||
|
try { |
||||||
|
final CodedOutputByteBufferNano output = |
||||||
|
CodedOutputByteBufferNano.newInstance(data, offset, length); |
||||||
|
msg.writeTo(output); |
||||||
|
output.checkNoSpaceLeft(); |
||||||
|
} catch (IOException e) { |
||||||
|
throw new RuntimeException("Serializing to a byte array threw an IOException " |
||||||
|
+ "(should never happen)."); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Parse {@code data} as a message of this type and merge it with the |
||||||
|
* message being built. |
||||||
|
*/ |
||||||
|
public static final MessageNano mergeFrom(MessageNano msg, final byte[] data) |
||||||
|
throws InvalidProtocolBufferNanoException { |
||||||
|
return mergeFrom(msg, data, 0, data.length); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Parse {@code data} as a message of this type and merge it with the |
||||||
|
* message being built. |
||||||
|
*/ |
||||||
|
public static final MessageNano mergeFrom(MessageNano msg, final byte[] data, final int off, |
||||||
|
final int len) throws InvalidProtocolBufferNanoException { |
||||||
|
try { |
||||||
|
final CodedInputByteBufferNano input = |
||||||
|
CodedInputByteBufferNano.newInstance(data, off, len); |
||||||
|
msg.mergeFrom(input); |
||||||
|
input.checkLastTagWas(0); |
||||||
|
return msg; |
||||||
|
} catch (InvalidProtocolBufferNanoException e) { |
||||||
|
throw e; |
||||||
|
} catch (IOException e) { |
||||||
|
throw new RuntimeException("Reading from a byte array threw an IOException (should " |
||||||
|
+ "never happen)."); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,138 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2013 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
package com.google.protobuf.nano; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
/** |
||||||
|
* This class is used internally by the Protocol Buffer library and generated |
||||||
|
* message implementations. It is public only because those generated messages |
||||||
|
* do not reside in the {@code protobuf} package. Others should not use this |
||||||
|
* class directly. |
||||||
|
* |
||||||
|
* This class contains constants and helper functions useful for dealing with |
||||||
|
* the Protocol Buffer wire format. |
||||||
|
* |
||||||
|
* @author kenton@google.com Kenton Varda |
||||||
|
*/ |
||||||
|
public final class WireFormatNano { |
||||||
|
// Do not allow instantiation.
|
||||||
|
private WireFormatNano() {} |
||||||
|
|
||||||
|
static final int WIRETYPE_VARINT = 0; |
||||||
|
static final int WIRETYPE_FIXED64 = 1; |
||||||
|
static final int WIRETYPE_LENGTH_DELIMITED = 2; |
||||||
|
static final int WIRETYPE_START_GROUP = 3; |
||||||
|
static final int WIRETYPE_END_GROUP = 4; |
||||||
|
static final int WIRETYPE_FIXED32 = 5; |
||||||
|
|
||||||
|
static final int TAG_TYPE_BITS = 3; |
||||||
|
static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1; |
||||||
|
|
||||||
|
/** Given a tag value, determines the wire type (the lower 3 bits). */ |
||||||
|
static int getTagWireType(final int tag) { |
||||||
|
return tag & TAG_TYPE_MASK; |
||||||
|
} |
||||||
|
|
||||||
|
/** Given a tag value, determines the field number (the upper 29 bits). */ |
||||||
|
public static int getTagFieldNumber(final int tag) { |
||||||
|
return tag >>> TAG_TYPE_BITS; |
||||||
|
} |
||||||
|
|
||||||
|
/** Makes a tag value given a field number and wire type. */ |
||||||
|
static int makeTag(final int fieldNumber, final int wireType) { |
||||||
|
return (fieldNumber << TAG_TYPE_BITS) | wireType; |
||||||
|
} |
||||||
|
|
||||||
|
// Field numbers for feilds in MessageSet wire format.
|
||||||
|
static final int MESSAGE_SET_ITEM = 1; |
||||||
|
static final int MESSAGE_SET_TYPE_ID = 2; |
||||||
|
static final int MESSAGE_SET_MESSAGE = 3; |
||||||
|
|
||||||
|
// Tag numbers.
|
||||||
|
static final int MESSAGE_SET_ITEM_TAG = |
||||||
|
makeTag(MESSAGE_SET_ITEM, WIRETYPE_START_GROUP); |
||||||
|
static final int MESSAGE_SET_ITEM_END_TAG = |
||||||
|
makeTag(MESSAGE_SET_ITEM, WIRETYPE_END_GROUP); |
||||||
|
static final int MESSAGE_SET_TYPE_ID_TAG = |
||||||
|
makeTag(MESSAGE_SET_TYPE_ID, WIRETYPE_VARINT); |
||||||
|
static final int MESSAGE_SET_MESSAGE_TAG = |
||||||
|
makeTag(MESSAGE_SET_MESSAGE, WIRETYPE_LENGTH_DELIMITED); |
||||||
|
|
||||||
|
public static final int EMPTY_INT_ARRAY[] = {}; |
||||||
|
public static final long EMPTY_LONG_ARRAY[] = {}; |
||||||
|
public static final float EMPTY_FLOAT_ARRAY[] = {}; |
||||||
|
public static final double EMPTY_DOUBLE_ARRAY[] = {}; |
||||||
|
public static final boolean EMPTY_BOOLEAN_ARRAY[] = {}; |
||||||
|
public static final String EMPTY_STRING_ARRAY[] = {}; |
||||||
|
public static final byte[] EMPTY_BYTES_ARRAY[] = {}; |
||||||
|
public static final byte[] EMPTY_BYTES = {}; |
||||||
|
|
||||||
|
/** |
||||||
|
* Called by subclasses to parse an unknown field. |
||||||
|
* @return {@code true} unless the tag is an end-group tag. |
||||||
|
*/ |
||||||
|
public static boolean parseUnknownField( |
||||||
|
final CodedInputByteBufferNano input, |
||||||
|
final int tag) throws IOException { |
||||||
|
return input.skipField(tag); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Computes the array length of a repeated field. We assume that in the common case repeated |
||||||
|
* fields are contiguously serialized but we still correctly handle interspersed values of a |
||||||
|
* repeated field (but with extra allocations). |
||||||
|
* |
||||||
|
* Rewinds to current input position before returning. |
||||||
|
* |
||||||
|
* @param input stream input, pointing to the byte after the first tag |
||||||
|
* @param tag repeated field tag just read |
||||||
|
* @return length of array |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public static final int getRepeatedFieldArrayLength( |
||||||
|
final CodedInputByteBufferNano input, |
||||||
|
final int tag) throws IOException { |
||||||
|
int arrayLength = 1; |
||||||
|
int startPos = input.getPosition(); |
||||||
|
input.skipField(tag); |
||||||
|
while (input.getBytesUntilLimit() > 0) { |
||||||
|
int thisTag = input.readTag(); |
||||||
|
if (thisTag != tag) { |
||||||
|
break; |
||||||
|
} |
||||||
|
input.skipField(tag); |
||||||
|
arrayLength++; |
||||||
|
} |
||||||
|
input.rewindToPosition(startPos); |
||||||
|
return arrayLength; |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,96 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <map> |
||||||
|
#include <string> |
||||||
|
|
||||||
|
#include <google/protobuf/compiler/javanano/javanano_params.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_enum.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_helpers.h> |
||||||
|
#include <google/protobuf/io/printer.h> |
||||||
|
#include <google/protobuf/descriptor.pb.h> |
||||||
|
#include <google/protobuf/stubs/strutil.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Params& params) |
||||||
|
: params_(params), descriptor_(descriptor) { |
||||||
|
for (int i = 0; i < descriptor_->value_count(); i++) { |
||||||
|
const EnumValueDescriptor* value = descriptor_->value(i); |
||||||
|
const EnumValueDescriptor* canonical_value = |
||||||
|
descriptor_->FindValueByNumber(value->number()); |
||||||
|
|
||||||
|
if (value == canonical_value) { |
||||||
|
canonical_values_.push_back(value); |
||||||
|
} else { |
||||||
|
Alias alias; |
||||||
|
alias.value = value; |
||||||
|
alias.canonical_value = canonical_value; |
||||||
|
aliases_.push_back(alias); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
EnumGenerator::~EnumGenerator() {} |
||||||
|
|
||||||
|
void EnumGenerator::Generate(io::Printer* printer) { |
||||||
|
printer->Print("// enum $classname$\n", "classname", descriptor_->name()); |
||||||
|
for (int i = 0; i < canonical_values_.size(); i++) { |
||||||
|
map<string, string> vars; |
||||||
|
vars["name"] = canonical_values_[i]->name(); |
||||||
|
vars["canonical_value"] = SimpleItoa(canonical_values_[i]->number()); |
||||||
|
printer->Print(vars, |
||||||
|
"public static final int $name$ = $canonical_value$;\n"); |
||||||
|
} |
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
for (int i = 0; i < aliases_.size(); i++) { |
||||||
|
map<string, string> vars; |
||||||
|
vars["name"] = aliases_[i].value->name(); |
||||||
|
vars["canonical_name"] = aliases_[i].canonical_value->name(); |
||||||
|
printer->Print(vars, |
||||||
|
"public static final int $name$ = $canonical_name$;\n"); |
||||||
|
} |
||||||
|
|
||||||
|
printer->Print("\n"); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,87 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__ |
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__ |
||||||
|
|
||||||
|
#include <string> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
#include <google/protobuf/compiler/javanano/javanano_params.h> |
||||||
|
#include <google/protobuf/descriptor.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace io { |
||||||
|
class Printer; // printer.h
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
class EnumGenerator { |
||||||
|
public: |
||||||
|
explicit EnumGenerator(const EnumDescriptor* descriptor, const Params& params); |
||||||
|
~EnumGenerator(); |
||||||
|
|
||||||
|
void Generate(io::Printer* printer); |
||||||
|
|
||||||
|
private: |
||||||
|
const Params& params_; |
||||||
|
const EnumDescriptor* descriptor_; |
||||||
|
|
||||||
|
// The proto language allows multiple enum constants to have the same numeric
|
||||||
|
// value. Java, however, does not allow multiple enum constants to be
|
||||||
|
// considered equivalent. We treat the first defined constant for any
|
||||||
|
// given numeric value as "canonical" and the rest as aliases of that
|
||||||
|
// canonical value.
|
||||||
|
vector<const EnumValueDescriptor*> canonical_values_; |
||||||
|
|
||||||
|
struct Alias { |
||||||
|
const EnumValueDescriptor* value; |
||||||
|
const EnumValueDescriptor* canonical_value; |
||||||
|
}; |
||||||
|
vector<Alias> aliases_; |
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__
|
@ -0,0 +1,266 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <map> |
||||||
|
#include <string> |
||||||
|
|
||||||
|
#include <google/protobuf/compiler/javanano/javanano_enum_field.h> |
||||||
|
#include <google/protobuf/stubs/common.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_helpers.h> |
||||||
|
#include <google/protobuf/io/printer.h> |
||||||
|
#include <google/protobuf/wire_format.h> |
||||||
|
#include <google/protobuf/stubs/strutil.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
|
||||||
|
// repeat code between this and the other field types.
|
||||||
|
void SetEnumVariables(const Params& params, |
||||||
|
const FieldDescriptor* descriptor, map<string, string>* variables) { |
||||||
|
(*variables)["name"] = |
||||||
|
UnderscoresToCamelCase(descriptor); |
||||||
|
(*variables)["capitalized_name"] = |
||||||
|
UnderscoresToCapitalizedCamelCase(descriptor); |
||||||
|
(*variables)["number"] = SimpleItoa(descriptor->number()); |
||||||
|
(*variables)["type"] = "int"; |
||||||
|
(*variables)["default"] = DefaultValue(params, descriptor); |
||||||
|
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); |
||||||
|
(*variables)["tag_size"] = SimpleItoa( |
||||||
|
internal::WireFormat::TagSize(descriptor->number(), descriptor->type())); |
||||||
|
(*variables)["message_name"] = descriptor->containing_type()->name(); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
EnumFieldGenerator:: |
||||||
|
EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params) |
||||||
|
: FieldGenerator(params), descriptor_(descriptor) { |
||||||
|
SetEnumVariables(params, descriptor, &variables_); |
||||||
|
} |
||||||
|
|
||||||
|
EnumFieldGenerator::~EnumFieldGenerator() {} |
||||||
|
|
||||||
|
void EnumFieldGenerator:: |
||||||
|
GenerateMembers(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"public int $name$ = $default$;\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void EnumFieldGenerator:: |
||||||
|
GenerateMergingCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, "$name$ = other.$name$;\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void EnumFieldGenerator:: |
||||||
|
GenerateParsingCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
" $name$ = input.readInt32();\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void EnumFieldGenerator:: |
||||||
|
GenerateSerializationCode(io::Printer* printer) const { |
||||||
|
if (descriptor_->is_required()) { |
||||||
|
printer->Print(variables_, |
||||||
|
"output.writeInt32($number$, $name$);\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"if ($name$ != $default$) {\n" |
||||||
|
" output.writeInt32($number$, $name$);\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void EnumFieldGenerator:: |
||||||
|
GenerateSerializedSizeCode(io::Printer* printer) const { |
||||||
|
if (descriptor_->is_required()) { |
||||||
|
printer->Print(variables_, |
||||||
|
"size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" |
||||||
|
" .computeInt32Size($number$, $name$);\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"if ($name$ != $default$) {\n" |
||||||
|
" size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" |
||||||
|
" .computeInt32Size($number$, $name$);\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
string EnumFieldGenerator::GetBoxedType() const { |
||||||
|
return ClassName(params_, descriptor_->enum_type()); |
||||||
|
} |
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
RepeatedEnumFieldGenerator:: |
||||||
|
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params) |
||||||
|
: FieldGenerator(params), descriptor_(descriptor) { |
||||||
|
SetEnumVariables(params, descriptor, &variables_); |
||||||
|
} |
||||||
|
|
||||||
|
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} |
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator:: |
||||||
|
GenerateMembers(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"public int[] $name$ = com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY;\n"); |
||||||
|
if (descriptor_->options().packed()) { |
||||||
|
printer->Print(variables_, |
||||||
|
"private int $name$MemoizedSerializedSize;\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator:: |
||||||
|
GenerateMergingCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"if (other.$name$.length > 0) {\n" |
||||||
|
" int[] merged = java.util.Arrays.copyOf(result.$name$, result.$name$.length + other.$name$.length);\n" |
||||||
|
" java.lang.System.arraycopy(other.$name$, 0, merged, results.$name$.length, other.$name$.length);\n" |
||||||
|
" result.$name$ = merged;\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator:: |
||||||
|
GenerateParsingCode(io::Printer* printer) const { |
||||||
|
// First, figure out the length of the array, then parse.
|
||||||
|
if (descriptor_->options().packed()) { |
||||||
|
printer->Print(variables_, |
||||||
|
"int length = input.readRawVarint32();\n" |
||||||
|
"int limit = input.pushLimit(length);\n" |
||||||
|
"// First pass to compute array length.\n" |
||||||
|
"int arrayLength = 0;\n" |
||||||
|
"int startPos = input.getPosition();\n" |
||||||
|
"while (input.getBytesUntilLimit() > 0) {\n" |
||||||
|
" input.readInt32();\n" |
||||||
|
" arrayLength++;\n" |
||||||
|
"}\n" |
||||||
|
"input.rewindToPosition(startPos);\n" |
||||||
|
"$name$ = new $type$[arrayLength];\n" |
||||||
|
"for (int i = 0; i < arrayLength; i++) {\n" |
||||||
|
" $name$[i] = input.readInt32();\n" |
||||||
|
"}\n" |
||||||
|
"input.popLimit(limit);\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"int arrayLength = com.google.protobuf.nano.WireFormatNano.getRepeatedFieldArrayLength(input, $tag$);\n" |
||||||
|
"int i = $name$.length;\n" |
||||||
|
"$name$ = java.util.Arrays.copyOf($name$, $name$.length + arrayLength);\n" |
||||||
|
"for (; i < $name$.length - 1; i++) {\n" |
||||||
|
" $name$[i] = input.readInt32();\n" |
||||||
|
" input.readTag();\n" |
||||||
|
"}\n" |
||||||
|
"// Last one without readTag.\n" |
||||||
|
"$name$[i] = input.readInt32();\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator:: |
||||||
|
GenerateSerializationCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"if ($name$.length > 0) {\n"); |
||||||
|
printer->Indent(); |
||||||
|
|
||||||
|
if (descriptor_->options().packed()) { |
||||||
|
printer->Print(variables_, |
||||||
|
"output.writeRawVarint32($tag$);\n" |
||||||
|
"output.writeRawVarint32($name$MemoizedSerializedSize);\n" |
||||||
|
"for (int element : $name$) {\n" |
||||||
|
" output.writeRawVarint32(element);\n" |
||||||
|
"}\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"for (int element : $name$) {\n" |
||||||
|
" output.writeInt32($number$, element);\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
printer->Outdent(); |
||||||
|
printer->Print(variables_, |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void RepeatedEnumFieldGenerator:: |
||||||
|
GenerateSerializedSizeCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"if ($name$.length > 0) {\n"); |
||||||
|
printer->Indent(); |
||||||
|
|
||||||
|
printer->Print(variables_, |
||||||
|
"int dataSize = 0;\n" |
||||||
|
"for (int element : $name$) {\n" |
||||||
|
" dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" |
||||||
|
" .computeInt32SizeNoTag(element);\n" |
||||||
|
"}\n"); |
||||||
|
|
||||||
|
printer->Print( |
||||||
|
"size += dataSize;\n"); |
||||||
|
if (descriptor_->options().packed()) { |
||||||
|
// cache the data size for packed fields.
|
||||||
|
printer->Print(variables_, |
||||||
|
"size += $tag_size$;\n" |
||||||
|
"size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" |
||||||
|
" .computeRawVarint32Size(dataSize);\n" |
||||||
|
"$name$MemoizedSerializedSize = dataSize;\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"size += $tag_size$ * $name$.length;\n"); |
||||||
|
} |
||||||
|
|
||||||
|
printer->Outdent(); |
||||||
|
|
||||||
|
// set cached size to 0 for empty packed fields.
|
||||||
|
if (descriptor_->options().packed()) { |
||||||
|
printer->Print(variables_, |
||||||
|
"} else {\n" |
||||||
|
" $name$MemoizedSerializedSize = 0;\n" |
||||||
|
"}\n"); |
||||||
|
} else { |
||||||
|
printer->Print( |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
string RepeatedEnumFieldGenerator::GetBoxedType() const { |
||||||
|
return ClassName(params_, descriptor_->enum_type()); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,94 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__ |
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__ |
||||||
|
|
||||||
|
#include <map> |
||||||
|
#include <string> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_field.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
class EnumFieldGenerator : public FieldGenerator { |
||||||
|
public: |
||||||
|
explicit EnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params); |
||||||
|
~EnumFieldGenerator(); |
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GenerateMembers(io::Printer* printer) const; |
||||||
|
void GenerateMergingCode(io::Printer* printer) const; |
||||||
|
void GenerateParsingCode(io::Printer* printer) const; |
||||||
|
void GenerateSerializationCode(io::Printer* printer) const; |
||||||
|
void GenerateSerializedSizeCode(io::Printer* printer) const; |
||||||
|
|
||||||
|
string GetBoxedType() const; |
||||||
|
|
||||||
|
private: |
||||||
|
const FieldDescriptor* descriptor_; |
||||||
|
map<string, string> variables_; |
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); |
||||||
|
}; |
||||||
|
|
||||||
|
class RepeatedEnumFieldGenerator : public FieldGenerator { |
||||||
|
public: |
||||||
|
explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params); |
||||||
|
~RepeatedEnumFieldGenerator(); |
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GenerateMembers(io::Printer* printer) const; |
||||||
|
void GenerateMergingCode(io::Printer* printer) const; |
||||||
|
void GenerateParsingCode(io::Printer* printer) const; |
||||||
|
void GenerateSerializationCode(io::Printer* printer) const; |
||||||
|
void GenerateSerializedSizeCode(io::Printer* printer) const; |
||||||
|
|
||||||
|
string GetBoxedType() const; |
||||||
|
|
||||||
|
private: |
||||||
|
const FieldDescriptor* descriptor_; |
||||||
|
map<string, string> variables_; |
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
|
@ -0,0 +1,102 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/javanano/javanano_field.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_helpers.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_primitive_field.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_enum_field.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_message_field.h> |
||||||
|
#include <google/protobuf/stubs/common.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
FieldGenerator::~FieldGenerator() {} |
||||||
|
|
||||||
|
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, const Params ¶ms) |
||||||
|
: descriptor_(descriptor), |
||||||
|
field_generators_( |
||||||
|
new scoped_ptr<FieldGenerator>[descriptor->field_count()]), |
||||||
|
extension_generators_( |
||||||
|
new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) { |
||||||
|
|
||||||
|
// Construct all the FieldGenerators.
|
||||||
|
for (int i = 0; i < descriptor->field_count(); i++) { |
||||||
|
field_generators_[i].reset(MakeGenerator(descriptor->field(i), params)); |
||||||
|
} |
||||||
|
for (int i = 0; i < descriptor->extension_count(); i++) { |
||||||
|
extension_generators_[i].reset(MakeGenerator(descriptor->extension(i), params)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, const Params ¶ms) { |
||||||
|
if (field->is_repeated()) { |
||||||
|
switch (GetJavaType(field)) { |
||||||
|
case JAVATYPE_MESSAGE: |
||||||
|
return new RepeatedMessageFieldGenerator(field, params); |
||||||
|
case JAVATYPE_ENUM: |
||||||
|
return new RepeatedEnumFieldGenerator(field, params); |
||||||
|
default: |
||||||
|
return new RepeatedPrimitiveFieldGenerator(field, params); |
||||||
|
} |
||||||
|
} else { |
||||||
|
switch (GetJavaType(field)) { |
||||||
|
case JAVATYPE_MESSAGE: |
||||||
|
return new MessageFieldGenerator(field, params); |
||||||
|
case JAVATYPE_ENUM: |
||||||
|
return new EnumFieldGenerator(field, params); |
||||||
|
default: |
||||||
|
return new PrimitiveFieldGenerator(field, params); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
FieldGeneratorMap::~FieldGeneratorMap() {} |
||||||
|
|
||||||
|
const FieldGenerator& FieldGeneratorMap::get( |
||||||
|
const FieldDescriptor* field) const { |
||||||
|
GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); |
||||||
|
return *field_generators_[field->index()]; |
||||||
|
} |
||||||
|
|
||||||
|
const FieldGenerator& FieldGeneratorMap::get_extension(int index) const { |
||||||
|
return *extension_generators_[index]; |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,98 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__ |
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__ |
||||||
|
|
||||||
|
#include <string> |
||||||
|
#include <google/protobuf/stubs/common.h> |
||||||
|
#include <google/protobuf/descriptor.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_params.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace io { |
||||||
|
class Printer; // printer.h
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
class FieldGenerator { |
||||||
|
public: |
||||||
|
//FieldGenerator() {}
|
||||||
|
FieldGenerator(const Params& params) : params_(params) {} |
||||||
|
virtual ~FieldGenerator(); |
||||||
|
|
||||||
|
virtual void GenerateMembers(io::Printer* printer) const = 0; |
||||||
|
virtual void GenerateMergingCode(io::Printer* printer) const = 0; |
||||||
|
virtual void GenerateParsingCode(io::Printer* printer) const = 0; |
||||||
|
virtual void GenerateSerializationCode(io::Printer* printer) const = 0; |
||||||
|
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; |
||||||
|
|
||||||
|
virtual string GetBoxedType() const = 0; |
||||||
|
|
||||||
|
protected: |
||||||
|
const Params& params_; |
||||||
|
private: |
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); |
||||||
|
}; |
||||||
|
|
||||||
|
// Convenience class which constructs FieldGenerators for a Descriptor.
|
||||||
|
class FieldGeneratorMap { |
||||||
|
public: |
||||||
|
explicit FieldGeneratorMap(const Descriptor* descriptor, const Params ¶ms); |
||||||
|
~FieldGeneratorMap(); |
||||||
|
|
||||||
|
const FieldGenerator& get(const FieldDescriptor* field) const; |
||||||
|
const FieldGenerator& get_extension(int index) const; |
||||||
|
|
||||||
|
private: |
||||||
|
const Descriptor* descriptor_; |
||||||
|
scoped_array<scoped_ptr<FieldGenerator> > field_generators_; |
||||||
|
scoped_array<scoped_ptr<FieldGenerator> > extension_generators_; |
||||||
|
|
||||||
|
static FieldGenerator* MakeGenerator(const FieldDescriptor* field, const Params ¶ms); |
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
|
@ -0,0 +1,251 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/javanano/javanano_file.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_enum.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_helpers.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_message.h> |
||||||
|
#include <google/protobuf/compiler/code_generator.h> |
||||||
|
#include <google/protobuf/io/printer.h> |
||||||
|
#include <google/protobuf/io/zero_copy_stream.h> |
||||||
|
#include <google/protobuf/descriptor.pb.h> |
||||||
|
#include <google/protobuf/stubs/strutil.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
// Recursively searches the given message to see if it contains any extensions.
|
||||||
|
bool UsesExtensions(const Message& message) { |
||||||
|
const Reflection* reflection = message.GetReflection(); |
||||||
|
|
||||||
|
// We conservatively assume that unknown fields are extensions.
|
||||||
|
if (reflection->GetUnknownFields(message).field_count() > 0) return true; |
||||||
|
|
||||||
|
vector<const FieldDescriptor*> fields; |
||||||
|
reflection->ListFields(message, &fields); |
||||||
|
|
||||||
|
for (int i = 0; i < fields.size(); i++) { |
||||||
|
if (fields[i]->is_extension()) return true; |
||||||
|
|
||||||
|
if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
||||||
|
if (fields[i]->is_repeated()) { |
||||||
|
int size = reflection->FieldSize(message, fields[i]); |
||||||
|
for (int j = 0; j < size; j++) { |
||||||
|
const Message& sub_message = |
||||||
|
reflection->GetRepeatedMessage(message, fields[i], j); |
||||||
|
if (UsesExtensions(sub_message)) return true; |
||||||
|
} |
||||||
|
} else { |
||||||
|
const Message& sub_message = reflection->GetMessage(message, fields[i]); |
||||||
|
if (UsesExtensions(sub_message)) return true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
FileGenerator::FileGenerator(const FileDescriptor* file, const Params& params) |
||||||
|
: file_(file), |
||||||
|
params_(params), |
||||||
|
java_package_(FileJavaPackage(params, file)), |
||||||
|
classname_(FileClassName(params, file)) {} |
||||||
|
|
||||||
|
FileGenerator::~FileGenerator() {} |
||||||
|
|
||||||
|
bool FileGenerator::Validate(string* error) { |
||||||
|
// Check for extensions
|
||||||
|
FileDescriptorProto file_proto; |
||||||
|
file_->CopyTo(&file_proto); |
||||||
|
if (UsesExtensions(file_proto)) { |
||||||
|
error->assign(file_->name()); |
||||||
|
error->append( |
||||||
|
": Java NANO_RUNTIME does not support extensions\""); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
// If there is no outer class name then there must be only
|
||||||
|
// message and no enums defined in the file scope.
|
||||||
|
if (!params_.has_java_outer_classname(file_->name())) { |
||||||
|
if (file_->message_type_count() != 1) { |
||||||
|
error->assign(file_->name()); |
||||||
|
error->append( |
||||||
|
": Java NANO_RUNTIME may only have 1 message if there is no 'option java_outer_classname'\""); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if (file_->enum_type_count() != 0) { |
||||||
|
error->assign(file_->name()); |
||||||
|
error->append( |
||||||
|
": Java NANO_RUNTIME must have an 'option java_outer_classname' if file scope enums are present\""); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Check that no class name matches the file's class name. This is a common
|
||||||
|
// problem that leads to Java compile errors that can be hard to understand.
|
||||||
|
// It's especially bad when using the java_multiple_files, since we would
|
||||||
|
// end up overwriting the outer class with one of the inner ones.
|
||||||
|
int found_fileName = 0; |
||||||
|
for (int i = 0; i < file_->enum_type_count(); i++) { |
||||||
|
if (file_->enum_type(i)->name() == classname_) { |
||||||
|
found_fileName += 1; |
||||||
|
} |
||||||
|
} |
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) { |
||||||
|
if (file_->message_type(i)->name() == classname_) { |
||||||
|
found_fileName += 1; |
||||||
|
} |
||||||
|
} |
||||||
|
if (file_->service_count() != 0) { |
||||||
|
error->assign(file_->name()); |
||||||
|
error->append( |
||||||
|
": Java NANO_RUNTIME does not support services\""); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if (found_fileName > 1) { |
||||||
|
error->assign(file_->name()); |
||||||
|
error->append( |
||||||
|
": Cannot generate Java output because there is more than one class name, \""); |
||||||
|
error->append(classname_); |
||||||
|
error->append( |
||||||
|
"\", matches the name of one of the types declared inside it. " |
||||||
|
"Please either rename the type or use the java_outer_classname " |
||||||
|
"option to specify a different outer class name for the .proto file." |
||||||
|
" -- FIX THIS MESSAGE"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
void FileGenerator::Generate(io::Printer* printer) { |
||||||
|
// We don't import anything because we refer to all classes by their
|
||||||
|
// fully-qualified names in the generated source.
|
||||||
|
printer->Print( |
||||||
|
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n" |
||||||
|
"\n"); |
||||||
|
if (!java_package_.empty()) { |
||||||
|
printer->Print( |
||||||
|
"package $package$;\n" |
||||||
|
"\n", |
||||||
|
"package", java_package_); |
||||||
|
} |
||||||
|
|
||||||
|
if (params_.has_java_outer_classname(file_->name())) { |
||||||
|
printer->Print( |
||||||
|
"public final class $classname$ {\n" |
||||||
|
" private $classname$() {}\n", |
||||||
|
"classname", classname_); |
||||||
|
printer->Indent(); |
||||||
|
} |
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
if (!params_.java_multiple_files()) { |
||||||
|
for (int i = 0; i < file_->enum_type_count(); i++) { |
||||||
|
EnumGenerator(file_->enum_type(i), params_).Generate(printer); |
||||||
|
} |
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) { |
||||||
|
MessageGenerator(file_->message_type(i), params_).Generate(printer); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Static variables.
|
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) { |
||||||
|
// TODO(kenton): Reuse MessageGenerator objects?
|
||||||
|
MessageGenerator(file_->message_type(i), params_).GenerateStaticVariables(printer); |
||||||
|
} |
||||||
|
|
||||||
|
if (params_.has_java_outer_classname(file_->name())) { |
||||||
|
printer->Outdent(); |
||||||
|
printer->Print( |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
template<typename GeneratorClass, typename DescriptorClass> |
||||||
|
static void GenerateSibling(const string& package_dir, |
||||||
|
const string& java_package, |
||||||
|
const DescriptorClass* descriptor, |
||||||
|
OutputDirectory* output_directory, |
||||||
|
vector<string>* file_list, |
||||||
|
const Params& params) { |
||||||
|
string filename = package_dir + descriptor->name() + ".java"; |
||||||
|
file_list->push_back(filename); |
||||||
|
|
||||||
|
scoped_ptr<io::ZeroCopyOutputStream> output( |
||||||
|
output_directory->Open(filename)); |
||||||
|
io::Printer printer(output.get(), '$'); |
||||||
|
|
||||||
|
printer.Print( |
||||||
|
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n" |
||||||
|
"\n"); |
||||||
|
if (!java_package.empty()) { |
||||||
|
printer.Print( |
||||||
|
"package $package$;\n" |
||||||
|
"\n", |
||||||
|
"package", java_package); |
||||||
|
} |
||||||
|
|
||||||
|
GeneratorClass(descriptor, params).Generate(&printer); |
||||||
|
} |
||||||
|
|
||||||
|
void FileGenerator::GenerateSiblings(const string& package_dir, |
||||||
|
OutputDirectory* output_directory, |
||||||
|
vector<string>* file_list) { |
||||||
|
if (params_.java_multiple_files()) { |
||||||
|
for (int i = 0; i < file_->enum_type_count(); i++) { |
||||||
|
GenerateSibling<EnumGenerator>(package_dir, java_package_, |
||||||
|
file_->enum_type(i), |
||||||
|
output_directory, file_list, params_); |
||||||
|
} |
||||||
|
for (int i = 0; i < file_->message_type_count(); i++) { |
||||||
|
GenerateSibling<MessageGenerator>(package_dir, java_package_, |
||||||
|
file_->message_type(i), |
||||||
|
output_directory, file_list, params_); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,94 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__ |
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__ |
||||||
|
|
||||||
|
#include <string> |
||||||
|
#include <vector> |
||||||
|
#include <google/protobuf/stubs/common.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_params.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
class FileDescriptor; // descriptor.h
|
||||||
|
namespace io { |
||||||
|
class Printer; // printer.h
|
||||||
|
} |
||||||
|
namespace compiler { |
||||||
|
class OutputDirectory; // code_generator.h
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
class FileGenerator { |
||||||
|
public: |
||||||
|
explicit FileGenerator(const FileDescriptor* file, const Params& params); |
||||||
|
~FileGenerator(); |
||||||
|
|
||||||
|
// Checks for problems that would otherwise lead to cryptic compile errors.
|
||||||
|
// Returns true if there are no problems, or writes an error description to
|
||||||
|
// the given string and returns false otherwise.
|
||||||
|
bool Validate(string* error); |
||||||
|
|
||||||
|
void Generate(io::Printer* printer); |
||||||
|
|
||||||
|
// If we aren't putting everything into one file, this will write all the
|
||||||
|
// files other than the outer file (i.e. one for each message, enum, and
|
||||||
|
// service type).
|
||||||
|
void GenerateSiblings(const string& package_dir, |
||||||
|
OutputDirectory* output_directory, |
||||||
|
vector<string>* file_list); |
||||||
|
|
||||||
|
const string& java_package() { return java_package_; } |
||||||
|
const string& classname() { return classname_; } |
||||||
|
|
||||||
|
private: |
||||||
|
const FileDescriptor* file_; |
||||||
|
const Params& params_; |
||||||
|
string java_package_; |
||||||
|
string classname_; |
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
|
@ -0,0 +1,170 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/javanano/javanano_params.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_generator.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_file.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_helpers.h> |
||||||
|
#include <google/protobuf/io/printer.h> |
||||||
|
#include <google/protobuf/io/zero_copy_stream.h> |
||||||
|
#include <google/protobuf/descriptor.pb.h> |
||||||
|
#include <google/protobuf/stubs/strutil.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
void UpdateParamsRecursively(Params& params, |
||||||
|
const FileDescriptor* file) { |
||||||
|
// Add any parameters for this file
|
||||||
|
if (file->options().has_java_outer_classname()) { |
||||||
|
params.set_java_outer_classname( |
||||||
|
file->name(), file->options().java_outer_classname()); |
||||||
|
} |
||||||
|
if (file->options().has_java_package()) { |
||||||
|
params.set_java_package( |
||||||
|
file->name(), file->options().java_package()); |
||||||
|
} |
||||||
|
|
||||||
|
// Loop through all dependent files recursively
|
||||||
|
// adding dep
|
||||||
|
for (int i = 0; i < file->dependency_count(); i++) { |
||||||
|
UpdateParamsRecursively(params, file->dependency(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
JavaNanoGenerator::JavaNanoGenerator() {} |
||||||
|
JavaNanoGenerator::~JavaNanoGenerator() {} |
||||||
|
|
||||||
|
bool JavaNanoGenerator::Generate(const FileDescriptor* file, |
||||||
|
const string& parameter, |
||||||
|
OutputDirectory* output_directory, |
||||||
|
string* error) const { |
||||||
|
vector<pair<string, string> > options; |
||||||
|
|
||||||
|
ParseGeneratorParameter(parameter, &options); |
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// parse generator options
|
||||||
|
|
||||||
|
// Name a file where we will write a list of generated file names, one
|
||||||
|
// per line.
|
||||||
|
string output_list_file; |
||||||
|
Params params(file->name()); |
||||||
|
|
||||||
|
// Get options from the proto file
|
||||||
|
if (file->options().has_java_multiple_files()) { |
||||||
|
params.set_java_multiple_files(file->options().java_multiple_files()); |
||||||
|
} |
||||||
|
|
||||||
|
// Update per file params
|
||||||
|
UpdateParamsRecursively(params, file); |
||||||
|
|
||||||
|
// Replace any existing options with ones from command line
|
||||||
|
for (int i = 0; i < options.size(); i++) { |
||||||
|
if (options[i].first == "output_list_file") { |
||||||
|
output_list_file = options[i].second; |
||||||
|
} else if (options[i].first == "java_package") { |
||||||
|
vector<string> parts; |
||||||
|
SplitStringUsing(options[i].second, "|", &parts); |
||||||
|
if (parts.size() != 2) { |
||||||
|
*error = "Bad java_package, expecting filename|PackageName found '" |
||||||
|
+ options[i].second + "'"; |
||||||
|
return false; |
||||||
|
} |
||||||
|
params.set_java_package(parts[0], parts[1]); |
||||||
|
} else if (options[i].first == "java_outer_classname") { |
||||||
|
vector<string> parts; |
||||||
|
SplitStringUsing(options[i].second, "|", &parts); |
||||||
|
if (parts.size() != 2) { |
||||||
|
*error = "Bad java_outer_classname, " |
||||||
|
"expecting filename|ClassName found '" |
||||||
|
+ options[i].second + "'"; |
||||||
|
return false; |
||||||
|
} |
||||||
|
params.set_java_outer_classname(parts[0], parts[1]); |
||||||
|
} else if (options[i].first == "java_multiple_files") { |
||||||
|
params.set_java_multiple_files(options[i].second == "true"); |
||||||
|
} else { |
||||||
|
*error = "Ignore unknown javanano generator option: " + options[i].first; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
FileGenerator file_generator(file, params); |
||||||
|
if (!file_generator.Validate(error)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
string package_dir = |
||||||
|
StringReplace(file_generator.java_package(), ".", "/", true); |
||||||
|
if (!package_dir.empty()) package_dir += "/"; |
||||||
|
|
||||||
|
vector<string> all_files; |
||||||
|
|
||||||
|
string java_filename = package_dir; |
||||||
|
java_filename += file_generator.classname(); |
||||||
|
java_filename += ".java"; |
||||||
|
all_files.push_back(java_filename); |
||||||
|
|
||||||
|
// Generate main java file.
|
||||||
|
scoped_ptr<io::ZeroCopyOutputStream> output( |
||||||
|
output_directory->Open(java_filename)); |
||||||
|
io::Printer printer(output.get(), '$'); |
||||||
|
file_generator.Generate(&printer); |
||||||
|
|
||||||
|
// Generate sibling files.
|
||||||
|
file_generator.GenerateSiblings(package_dir, output_directory, &all_files); |
||||||
|
|
||||||
|
// Generate output list if requested.
|
||||||
|
if (!output_list_file.empty()) { |
||||||
|
// Generate output list. This is just a simple text file placed in a
|
||||||
|
// deterministic location which lists the .java files being generated.
|
||||||
|
scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output( |
||||||
|
output_directory->Open(output_list_file)); |
||||||
|
io::Printer srclist_printer(srclist_raw_output.get(), '$'); |
||||||
|
for (int i = 0; i < all_files.size(); i++) { |
||||||
|
srclist_printer.Print("$filename$\n", "filename", all_files[i]); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace java
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,72 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
//
|
||||||
|
// Generates Java nano code for a given .proto file.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_NANO_GENERATOR_H__ |
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_JAVA_NANO_GENERATOR_H__ |
||||||
|
|
||||||
|
#include <string> |
||||||
|
#include <google/protobuf/compiler/code_generator.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
// CodeGenerator implementation which generates Java nano code. If you create your
|
||||||
|
// own protocol compiler binary and you want it to support Java output for the
|
||||||
|
// nano runtime, you can do so by registering an instance of this CodeGenerator with
|
||||||
|
// the CommandLineInterface in your main() function.
|
||||||
|
class LIBPROTOC_EXPORT JavaNanoGenerator : public CodeGenerator { |
||||||
|
public: |
||||||
|
JavaNanoGenerator(); |
||||||
|
~JavaNanoGenerator(); |
||||||
|
|
||||||
|
// implements CodeGenerator ----------------------------------------
|
||||||
|
bool Generate(const FileDescriptor* file, |
||||||
|
const string& parameter, |
||||||
|
OutputDirectory* output_directory, |
||||||
|
string* error) const; |
||||||
|
|
||||||
|
private: |
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaNanoGenerator); |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_NANO_GENERATOR_H__
|
@ -0,0 +1,404 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <vector> |
||||||
|
|
||||||
|
#include <google/protobuf/compiler/javanano/javanano_helpers.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_params.h> |
||||||
|
#include <google/protobuf/descriptor.pb.h> |
||||||
|
#include <google/protobuf/stubs/strutil.h> |
||||||
|
#include <google/protobuf/stubs/substitute.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
const char kThickSeparator[] = |
||||||
|
"// ===================================================================\n"; |
||||||
|
const char kThinSeparator[] = |
||||||
|
"// -------------------------------------------------------------------\n"; |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
const char* kDefaultPackage = ""; |
||||||
|
|
||||||
|
const string& FieldName(const FieldDescriptor* field) { |
||||||
|
// Groups are hacky: The name of the field is just the lower-cased name
|
||||||
|
// of the group type. In Java, though, we would like to retain the original
|
||||||
|
// capitalization of the type name.
|
||||||
|
if (field->type() == FieldDescriptor::TYPE_GROUP) { |
||||||
|
return field->message_type()->name(); |
||||||
|
} else { |
||||||
|
return field->name(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) { |
||||||
|
string result; |
||||||
|
// Note: I distrust ctype.h due to locales.
|
||||||
|
for (int i = 0; i < input.size(); i++) { |
||||||
|
if ('a' <= input[i] && input[i] <= 'z') { |
||||||
|
if (cap_next_letter) { |
||||||
|
result += input[i] + ('A' - 'a'); |
||||||
|
} else { |
||||||
|
result += input[i]; |
||||||
|
} |
||||||
|
cap_next_letter = false; |
||||||
|
} else if ('A' <= input[i] && input[i] <= 'Z') { |
||||||
|
if (i == 0 && !cap_next_letter) { |
||||||
|
// Force first letter to lower-case unless explicitly told to
|
||||||
|
// capitalize it.
|
||||||
|
result += input[i] + ('a' - 'A'); |
||||||
|
} else { |
||||||
|
// Capital letters after the first are left as-is.
|
||||||
|
result += input[i]; |
||||||
|
} |
||||||
|
cap_next_letter = false; |
||||||
|
} else if ('0' <= input[i] && input[i] <= '9') { |
||||||
|
result += input[i]; |
||||||
|
cap_next_letter = true; |
||||||
|
} else { |
||||||
|
cap_next_letter = true; |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
string UnderscoresToCamelCase(const FieldDescriptor* field) { |
||||||
|
return UnderscoresToCamelCaseImpl(FieldName(field), false); |
||||||
|
} |
||||||
|
|
||||||
|
string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { |
||||||
|
return UnderscoresToCamelCaseImpl(FieldName(field), true); |
||||||
|
} |
||||||
|
|
||||||
|
string UnderscoresToCamelCase(const MethodDescriptor* method) { |
||||||
|
return UnderscoresToCamelCaseImpl(method->name(), false); |
||||||
|
} |
||||||
|
|
||||||
|
string StripProto(const string& filename) { |
||||||
|
if (HasSuffixString(filename, ".protodevel")) { |
||||||
|
return StripSuffixString(filename, ".protodevel"); |
||||||
|
} else { |
||||||
|
return StripSuffixString(filename, ".proto"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
string FileClassName(const Params& params, const FileDescriptor* file) { |
||||||
|
string name; |
||||||
|
|
||||||
|
if (params.has_java_outer_classname(file->name())) { |
||||||
|
name = params.java_outer_classname(file->name()); |
||||||
|
} else { |
||||||
|
if ((file->message_type_count() == 1) |
||||||
|
|| (file->enum_type_count() == 0)) { |
||||||
|
// If no outer calls and only one message then
|
||||||
|
// use the message name as the file name
|
||||||
|
name = file->message_type(0)->name(); |
||||||
|
} else { |
||||||
|
// Use the filename it self with underscores removed
|
||||||
|
// and a CamelCase style name.
|
||||||
|
string basename; |
||||||
|
string::size_type last_slash = file->name().find_last_of('/'); |
||||||
|
if (last_slash == string::npos) { |
||||||
|
basename = file->name(); |
||||||
|
} else { |
||||||
|
basename = file->name().substr(last_slash + 1); |
||||||
|
} |
||||||
|
name = UnderscoresToCamelCaseImpl(StripProto(basename), true); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return name; |
||||||
|
} |
||||||
|
|
||||||
|
string FileJavaPackage(const Params& params, const FileDescriptor* file) { |
||||||
|
if (params.has_java_package(file->name())) { |
||||||
|
return params.java_package(file->name()); |
||||||
|
} else { |
||||||
|
string result = kDefaultPackage; |
||||||
|
if (!file->package().empty()) { |
||||||
|
if (!result.empty()) result += '.'; |
||||||
|
result += file->package(); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
string ToJavaName(const Params& params, const string& full_name, |
||||||
|
const FileDescriptor* file) { |
||||||
|
string result; |
||||||
|
if (params.java_multiple_files()) { |
||||||
|
result = FileJavaPackage(params, file); |
||||||
|
} else { |
||||||
|
result = ClassName(params, file); |
||||||
|
} |
||||||
|
if (file->package().empty()) { |
||||||
|
result += '.'; |
||||||
|
result += full_name; |
||||||
|
} else { |
||||||
|
// Strip the proto package from full_name since we've replaced it with
|
||||||
|
// the Java package. If there isn't an outer classname then strip it too.
|
||||||
|
int sizeToSkipPackageName = file->package().size(); |
||||||
|
int sizeToSkipOutClassName; |
||||||
|
if (params.has_java_outer_classname(file->name())) { |
||||||
|
sizeToSkipOutClassName = 0; |
||||||
|
} else { |
||||||
|
sizeToSkipOutClassName = |
||||||
|
full_name.find_first_of('.', sizeToSkipPackageName + 1); |
||||||
|
} |
||||||
|
int sizeToSkip = sizeToSkipOutClassName > 0 ? |
||||||
|
sizeToSkipOutClassName : sizeToSkipPackageName; |
||||||
|
string class_name = full_name.substr(sizeToSkip + 1); |
||||||
|
if (class_name == FileClassName(params, file)) { |
||||||
|
// Done class_name is already present.
|
||||||
|
} else { |
||||||
|
result += '.'; |
||||||
|
result += class_name; |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
string ClassName(const Params& params, const FileDescriptor* descriptor) { |
||||||
|
string result = FileJavaPackage(params, descriptor); |
||||||
|
if (!result.empty()) result += '.'; |
||||||
|
result += FileClassName(params, descriptor); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
string ClassName(const Params& params, const EnumDescriptor* descriptor) { |
||||||
|
string result; |
||||||
|
const FileDescriptor* file = descriptor->file(); |
||||||
|
const string file_name = file->name(); |
||||||
|
const string full_name = descriptor->full_name(); |
||||||
|
|
||||||
|
// Remove enum class name as we use int's for enums
|
||||||
|
string base_name = full_name.substr(0, full_name.find_last_of('.')); |
||||||
|
|
||||||
|
if (!file->package().empty()) { |
||||||
|
if (file->package() == base_name.substr(0, file->package().size())) { |
||||||
|
// Remove package name leaving just the parent class of the enum
|
||||||
|
int offset = file->package().size(); |
||||||
|
if (base_name.size() > offset) { |
||||||
|
// Remove period between package and class name if there is a classname
|
||||||
|
offset += 1; |
||||||
|
} |
||||||
|
base_name = base_name.substr(offset); |
||||||
|
} else { |
||||||
|
GOOGLE_LOG(FATAL) << "Expected package name to start an enum"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Construct the path name from the package and outer class
|
||||||
|
|
||||||
|
// Add the java package name if it exsits
|
||||||
|
if (params.has_java_package(file_name)) { |
||||||
|
result += params.java_package(file_name); |
||||||
|
} |
||||||
|
|
||||||
|
// Add the outer classname if it exists
|
||||||
|
if (params.has_java_outer_classname(file_name)) { |
||||||
|
if (!result.empty()) { |
||||||
|
result += "."; |
||||||
|
} |
||||||
|
result += params.java_outer_classname(file_name); |
||||||
|
} |
||||||
|
|
||||||
|
// Create the full class name from the base and path
|
||||||
|
if (!base_name.empty()) { |
||||||
|
if (!result.empty()) { |
||||||
|
result += "."; |
||||||
|
} |
||||||
|
result += base_name; |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
string FieldConstantName(const FieldDescriptor *field) { |
||||||
|
string name = field->name() + "_FIELD_NUMBER"; |
||||||
|
UpperString(&name); |
||||||
|
return name; |
||||||
|
} |
||||||
|
|
||||||
|
string FieldDefaultConstantName(const FieldDescriptor *field) { |
||||||
|
string name = field->name() + "_DEFAULT"; |
||||||
|
UpperString(&name); |
||||||
|
return name; |
||||||
|
} |
||||||
|
|
||||||
|
JavaType GetJavaType(FieldDescriptor::Type field_type) { |
||||||
|
switch (field_type) { |
||||||
|
case FieldDescriptor::TYPE_INT32: |
||||||
|
case FieldDescriptor::TYPE_UINT32: |
||||||
|
case FieldDescriptor::TYPE_SINT32: |
||||||
|
case FieldDescriptor::TYPE_FIXED32: |
||||||
|
case FieldDescriptor::TYPE_SFIXED32: |
||||||
|
return JAVATYPE_INT; |
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_INT64: |
||||||
|
case FieldDescriptor::TYPE_UINT64: |
||||||
|
case FieldDescriptor::TYPE_SINT64: |
||||||
|
case FieldDescriptor::TYPE_FIXED64: |
||||||
|
case FieldDescriptor::TYPE_SFIXED64: |
||||||
|
return JAVATYPE_LONG; |
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_FLOAT: |
||||||
|
return JAVATYPE_FLOAT; |
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_DOUBLE: |
||||||
|
return JAVATYPE_DOUBLE; |
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_BOOL: |
||||||
|
return JAVATYPE_BOOLEAN; |
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_STRING: |
||||||
|
return JAVATYPE_STRING; |
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_BYTES: |
||||||
|
return JAVATYPE_BYTES; |
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_ENUM: |
||||||
|
return JAVATYPE_ENUM; |
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_GROUP: |
||||||
|
case FieldDescriptor::TYPE_MESSAGE: |
||||||
|
return JAVATYPE_MESSAGE; |
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// types are added.
|
||||||
|
} |
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
||||||
|
return JAVATYPE_INT; |
||||||
|
} |
||||||
|
|
||||||
|
const char* BoxedPrimitiveTypeName(JavaType type) { |
||||||
|
switch (type) { |
||||||
|
case JAVATYPE_INT : return "java.lang.Integer"; |
||||||
|
case JAVATYPE_LONG : return "java.lang.Long"; |
||||||
|
case JAVATYPE_FLOAT : return "java.lang.Float"; |
||||||
|
case JAVATYPE_DOUBLE : return "java.lang.Double"; |
||||||
|
case JAVATYPE_BOOLEAN: return "java.lang.Boolean"; |
||||||
|
case JAVATYPE_STRING : return "java.lang.String"; |
||||||
|
case JAVATYPE_BYTES : return "byte[]"; |
||||||
|
case JAVATYPE_ENUM : return "java.lang.Integer"; |
||||||
|
case JAVATYPE_MESSAGE: return NULL; |
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// JavaTypes are added.
|
||||||
|
} |
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
string EmptyArrayName(const Params& params, const FieldDescriptor* field) { |
||||||
|
switch (GetJavaType(field)) { |
||||||
|
case JAVATYPE_INT : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY"; |
||||||
|
case JAVATYPE_LONG : return "com.google.protobuf.nano.WireFormatNano.EMPTY_LONG_ARRAY"; |
||||||
|
case JAVATYPE_FLOAT : return "com.google.protobuf.nano.WireFormatNano.EMPTY_FLOAT_ARRAY"; |
||||||
|
case JAVATYPE_DOUBLE : return "com.google.protobuf.nano.WireFormatNano.EMPTY_DOUBLE_ARRAY"; |
||||||
|
case JAVATYPE_BOOLEAN: return "com.google.protobuf.nano.WireFormatNano.EMPTY_BOOLEAN_ARRAY"; |
||||||
|
case JAVATYPE_STRING : return "com.google.protobuf.nano.WireFormatNano.EMPTY_STRING_ARRAY"; |
||||||
|
case JAVATYPE_BYTES : return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES_ARRAY"; |
||||||
|
case JAVATYPE_ENUM : return "com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY"; |
||||||
|
case JAVATYPE_MESSAGE: return ClassName(params, field->message_type()) + ".EMPTY_ARRAY"; |
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// JavaTypes are added.
|
||||||
|
} |
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
||||||
|
return ""; |
||||||
|
} |
||||||
|
|
||||||
|
string DefaultValue(const Params& params, const FieldDescriptor* field) { |
||||||
|
if (field->label() == FieldDescriptor::LABEL_REPEATED) { |
||||||
|
return EmptyArrayName(params, field); |
||||||
|
} |
||||||
|
|
||||||
|
// Switch on cpp_type since we need to know which default_value_* method
|
||||||
|
// of FieldDescriptor to call.
|
||||||
|
switch (field->cpp_type()) { |
||||||
|
case FieldDescriptor::CPPTYPE_INT32: |
||||||
|
return SimpleItoa(field->default_value_int32()); |
||||||
|
case FieldDescriptor::CPPTYPE_UINT32: |
||||||
|
// Need to print as a signed int since Java has no unsigned.
|
||||||
|
return SimpleItoa(static_cast<int32>(field->default_value_uint32())); |
||||||
|
case FieldDescriptor::CPPTYPE_INT64: |
||||||
|
return SimpleItoa(field->default_value_int64()) + "L"; |
||||||
|
case FieldDescriptor::CPPTYPE_UINT64: |
||||||
|
return SimpleItoa(static_cast<int64>(field->default_value_uint64())) + |
||||||
|
"L"; |
||||||
|
case FieldDescriptor::CPPTYPE_DOUBLE: |
||||||
|
return SimpleDtoa(field->default_value_double()) + "D"; |
||||||
|
case FieldDescriptor::CPPTYPE_FLOAT: |
||||||
|
return SimpleFtoa(field->default_value_float()) + "F"; |
||||||
|
case FieldDescriptor::CPPTYPE_BOOL: |
||||||
|
return field->default_value_bool() ? "true" : "false"; |
||||||
|
case FieldDescriptor::CPPTYPE_STRING: |
||||||
|
if (!field->default_value_string().empty()) { |
||||||
|
// Point it to the static final in the generated code.
|
||||||
|
return FieldDefaultConstantName(field); |
||||||
|
} else { |
||||||
|
if (field->type() == FieldDescriptor::TYPE_BYTES) { |
||||||
|
return "com.google.protobuf.nano.WireFormatNano.EMPTY_BYTES"; |
||||||
|
} else { |
||||||
|
return "\"\""; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
case FieldDescriptor::CPPTYPE_ENUM: |
||||||
|
return ClassName(params, field->enum_type()) + "." + |
||||||
|
field->default_value_enum()->name(); |
||||||
|
|
||||||
|
case FieldDescriptor::CPPTYPE_MESSAGE: |
||||||
|
return "null"; |
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// types are added.
|
||||||
|
} |
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
||||||
|
return ""; |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,132 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ |
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ |
||||||
|
|
||||||
|
#include <string> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_params.h> |
||||||
|
#include <google/protobuf/descriptor.pb.h> |
||||||
|
#include <google/protobuf/descriptor.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
// Commonly-used separator comments. Thick is a line of '=', thin is a line
|
||||||
|
// of '-'.
|
||||||
|
extern const char kThickSeparator[]; |
||||||
|
extern const char kThinSeparator[]; |
||||||
|
|
||||||
|
// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes
|
||||||
|
// "fooBarBaz" or "FooBarBaz", respectively.
|
||||||
|
string UnderscoresToCamelCase(const FieldDescriptor* field); |
||||||
|
string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); |
||||||
|
|
||||||
|
// Similar, but for method names. (Typically, this merely has the effect
|
||||||
|
// of lower-casing the first letter of the name.)
|
||||||
|
string UnderscoresToCamelCase(const MethodDescriptor* method); |
||||||
|
|
||||||
|
// Strips ".proto" or ".protodevel" from the end of a filename.
|
||||||
|
string StripProto(const string& filename); |
||||||
|
|
||||||
|
// Gets the unqualified class name for the file. Each .proto file becomes a
|
||||||
|
// single Java class, with all its contents nested in that class.
|
||||||
|
string FileClassName(const Params& params, const FileDescriptor* file); |
||||||
|
|
||||||
|
// Returns the file's Java package name.
|
||||||
|
string FileJavaPackage(const Params& params, const FileDescriptor* file); |
||||||
|
|
||||||
|
// Converts the given fully-qualified name in the proto namespace to its
|
||||||
|
// fully-qualified name in the Java namespace, given that it is in the given
|
||||||
|
// file.
|
||||||
|
string ToJavaName(const Params& params, const string& full_name, |
||||||
|
const FileDescriptor* file); |
||||||
|
|
||||||
|
// These return the fully-qualified class name corresponding to the given
|
||||||
|
// descriptor.
|
||||||
|
inline string ClassName(const Params& params, const Descriptor* descriptor) { |
||||||
|
return ToJavaName(params, descriptor->full_name(), descriptor->file()); |
||||||
|
} |
||||||
|
string ClassName(const Params& params, const EnumDescriptor* descriptor); |
||||||
|
inline string ClassName(const Params& params, |
||||||
|
const ServiceDescriptor* descriptor) { |
||||||
|
return ToJavaName(params, descriptor->full_name(), descriptor->file()); |
||||||
|
} |
||||||
|
inline string ExtensionIdentifierName(const Params& params, |
||||||
|
const FieldDescriptor* descriptor) { |
||||||
|
return ToJavaName(params, descriptor->full_name(), descriptor->file()); |
||||||
|
} |
||||||
|
string ClassName(const Params& params, const FileDescriptor* descriptor); |
||||||
|
|
||||||
|
// Get the unqualified name that should be used for a field's field
|
||||||
|
// number constant.
|
||||||
|
string FieldConstantName(const FieldDescriptor *field); |
||||||
|
|
||||||
|
string FieldDefaultConstantName(const FieldDescriptor *field); |
||||||
|
|
||||||
|
enum JavaType { |
||||||
|
JAVATYPE_INT, |
||||||
|
JAVATYPE_LONG, |
||||||
|
JAVATYPE_FLOAT, |
||||||
|
JAVATYPE_DOUBLE, |
||||||
|
JAVATYPE_BOOLEAN, |
||||||
|
JAVATYPE_STRING, |
||||||
|
JAVATYPE_BYTES, |
||||||
|
JAVATYPE_ENUM, |
||||||
|
JAVATYPE_MESSAGE |
||||||
|
}; |
||||||
|
|
||||||
|
JavaType GetJavaType(FieldDescriptor::Type field_type); |
||||||
|
|
||||||
|
inline JavaType GetJavaType(const FieldDescriptor* field) { |
||||||
|
return GetJavaType(field->type()); |
||||||
|
} |
||||||
|
|
||||||
|
// Get the fully-qualified class name for a boxed primitive type, e.g.
|
||||||
|
// "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message
|
||||||
|
// types.
|
||||||
|
const char* BoxedPrimitiveTypeName(JavaType type); |
||||||
|
|
||||||
|
string EmptyArrayName(const Params& params, const FieldDescriptor* field); |
||||||
|
|
||||||
|
string DefaultValue(const Params& params, const FieldDescriptor* field); |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
|
@ -0,0 +1,372 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <algorithm> |
||||||
|
#include <google/protobuf/stubs/hash.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_message.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_enum.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_helpers.h> |
||||||
|
#include <google/protobuf/stubs/strutil.h> |
||||||
|
#include <google/protobuf/io/printer.h> |
||||||
|
#include <google/protobuf/io/coded_stream.h> |
||||||
|
#include <google/protobuf/wire_format.h> |
||||||
|
#include <google/protobuf/descriptor.pb.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
using internal::WireFormat; |
||||||
|
using internal::WireFormatLite; |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) { |
||||||
|
// Print the field's proto-syntax definition as a comment. We don't want to
|
||||||
|
// print group bodies so we cut off after the first line.
|
||||||
|
string def = field->DebugString(); |
||||||
|
printer->Print("// $def$\n", |
||||||
|
"def", def.substr(0, def.find_first_of('\n'))); |
||||||
|
} |
||||||
|
|
||||||
|
struct FieldOrderingByNumber { |
||||||
|
inline bool operator()(const FieldDescriptor* a, |
||||||
|
const FieldDescriptor* b) const { |
||||||
|
return a->number() < b->number(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
// Sort the fields of the given Descriptor by number into a new[]'d array
|
||||||
|
// and return it.
|
||||||
|
const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { |
||||||
|
const FieldDescriptor** fields = |
||||||
|
new const FieldDescriptor*[descriptor->field_count()]; |
||||||
|
for (int i = 0; i < descriptor->field_count(); i++) { |
||||||
|
fields[i] = descriptor->field(i); |
||||||
|
} |
||||||
|
sort(fields, fields + descriptor->field_count(), |
||||||
|
FieldOrderingByNumber()); |
||||||
|
return fields; |
||||||
|
} |
||||||
|
|
||||||
|
// Get an identifier that uniquely identifies this type within the file.
|
||||||
|
// This is used to declare static variables related to this type at the
|
||||||
|
// outermost file scope.
|
||||||
|
string UniqueFileScopeIdentifier(const Descriptor* descriptor) { |
||||||
|
return "static_" + StringReplace(descriptor->full_name(), ".", "_", true); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params) |
||||||
|
: params_(params), |
||||||
|
descriptor_(descriptor), |
||||||
|
field_generators_(descriptor, params) { |
||||||
|
} |
||||||
|
|
||||||
|
MessageGenerator::~MessageGenerator() {} |
||||||
|
|
||||||
|
void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { |
||||||
|
// Generate static members for all nested types.
|
||||||
|
for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
||||||
|
// TODO(kenton): Reuse MessageGenerator objects?
|
||||||
|
MessageGenerator(descriptor_->nested_type(i), params_) |
||||||
|
.GenerateStaticVariables(printer); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void MessageGenerator::GenerateStaticVariableInitializers( |
||||||
|
io::Printer* printer) { |
||||||
|
// Generate static member initializers for all nested types.
|
||||||
|
for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
||||||
|
// TODO(kenton): Reuse MessageGenerator objects?
|
||||||
|
MessageGenerator(descriptor_->nested_type(i), params_) |
||||||
|
.GenerateStaticVariableInitializers(printer); |
||||||
|
} |
||||||
|
|
||||||
|
if (descriptor_->extension_count() != 0) { |
||||||
|
GOOGLE_LOG(FATAL) << "Extensions not supported in NANO_RUNTIME\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void MessageGenerator::Generate(io::Printer* printer) { |
||||||
|
bool is_own_file = |
||||||
|
params_.java_multiple_files() || ((descriptor_->containing_type() == NULL) |
||||||
|
&& !params_.has_java_outer_classname(descriptor_->file()->name())); |
||||||
|
|
||||||
|
#if 0 |
||||||
|
GOOGLE_LOG(INFO) << "is_own_file=" << is_own_file; |
||||||
|
GOOGLE_LOG(INFO) << "containing_type()=" << ((descriptor_->containing_type() == NULL) ? "NULL" : "not null"); |
||||||
|
GOOGLE_LOG(INFO) << "java_multiple_files()=" << params_.java_multiple_files(); |
||||||
|
GOOGLE_LOG(INFO) << "has_java_outer_classname()=" << params_.has_java_outer_classname(file_->name()); |
||||||
|
#endif |
||||||
|
|
||||||
|
if ((descriptor_->extension_count() != 0) |
||||||
|
|| (descriptor_->extension_range_count() != 0)) { |
||||||
|
GOOGLE_LOG(FATAL) << "Extensions not supported in NANO_RUNTIME\n"; |
||||||
|
} |
||||||
|
|
||||||
|
// Note: Fields (which will be emitted in the loop, below) may have the same names as fields in
|
||||||
|
// the inner or outer class. This causes Java warnings, but is not fatal, so we suppress those
|
||||||
|
// warnings here in the class declaration.
|
||||||
|
printer->Print( |
||||||
|
"@SuppressWarnings(\"hiding\")\n" |
||||||
|
"public $modifiers$ final class $classname$ extends\n" |
||||||
|
" com.google.protobuf.nano.MessageNano {\n", |
||||||
|
"modifiers", is_own_file ? "" : "static", |
||||||
|
"classname", descriptor_->name()); |
||||||
|
printer->Indent(); |
||||||
|
printer->Print( |
||||||
|
"public static final $classname$ EMPTY_ARRAY[] = {};\n" |
||||||
|
"public $classname$() {}\n" |
||||||
|
"\n", |
||||||
|
"classname", descriptor_->name()); |
||||||
|
|
||||||
|
// Nested types and extensions
|
||||||
|
for (int i = 0; i < descriptor_->enum_type_count(); i++) { |
||||||
|
EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer); |
||||||
|
} |
||||||
|
|
||||||
|
for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
||||||
|
MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer); |
||||||
|
} |
||||||
|
|
||||||
|
// Fields
|
||||||
|
for (int i = 0; i < descriptor_->field_count(); i++) { |
||||||
|
PrintFieldComment(printer, descriptor_->field(i)); |
||||||
|
field_generators_.get(descriptor_->field(i)).GenerateMembers(printer); |
||||||
|
printer->Print("\n"); |
||||||
|
} |
||||||
|
|
||||||
|
GenerateClear(printer); |
||||||
|
GenerateMessageSerializationMethods(printer); |
||||||
|
GenerateMergeFromMethods(printer); |
||||||
|
GenerateParseFromMethods(printer); |
||||||
|
|
||||||
|
printer->Outdent(); |
||||||
|
printer->Print("}\n\n"); |
||||||
|
} |
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
void MessageGenerator:: |
||||||
|
GenerateMessageSerializationMethods(io::Printer* printer) { |
||||||
|
scoped_array<const FieldDescriptor*> sorted_fields( |
||||||
|
SortFieldsByNumber(descriptor_)); |
||||||
|
|
||||||
|
if (descriptor_->extension_range_count() != 0) { |
||||||
|
GOOGLE_LOG(FATAL) << "Extensions not supported in NANO_RUNTIME\n"; |
||||||
|
} |
||||||
|
|
||||||
|
// writeTo only throws an exception if it contains one or more fields to write
|
||||||
|
if (descriptor_->field_count() > 0) { |
||||||
|
printer->Print( |
||||||
|
"@Override\n" |
||||||
|
"public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n" |
||||||
|
" throws java.io.IOException {\n"); |
||||||
|
} else { |
||||||
|
printer->Print( |
||||||
|
"@Override\n" |
||||||
|
"public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output) {\n"); |
||||||
|
} |
||||||
|
printer->Indent(); |
||||||
|
|
||||||
|
// Output the fields in sorted order
|
||||||
|
for (int i = 0; i < descriptor_->field_count(); i++) { |
||||||
|
GenerateSerializeOneField(printer, sorted_fields[i]); |
||||||
|
} |
||||||
|
|
||||||
|
printer->Outdent(); |
||||||
|
printer->Print( |
||||||
|
"}\n" |
||||||
|
"\n" |
||||||
|
"private int cachedSize = -1;\n" |
||||||
|
"@Override\n" |
||||||
|
"public int getCachedSize() {\n" |
||||||
|
" if (cachedSize < 0) {\n" |
||||||
|
" // getSerializedSize sets cachedSize\n" |
||||||
|
" getSerializedSize();\n" |
||||||
|
" }\n" |
||||||
|
" return cachedSize;\n" |
||||||
|
"}\n" |
||||||
|
"\n" |
||||||
|
"@Override\n" |
||||||
|
"public int getSerializedSize() {\n" |
||||||
|
" int size = 0;\n"); |
||||||
|
printer->Indent(); |
||||||
|
|
||||||
|
for (int i = 0; i < descriptor_->field_count(); i++) { |
||||||
|
field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer); |
||||||
|
} |
||||||
|
|
||||||
|
printer->Outdent(); |
||||||
|
printer->Print( |
||||||
|
" cachedSize = size;\n" |
||||||
|
" return size;\n" |
||||||
|
"}\n" |
||||||
|
"\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) { |
||||||
|
scoped_array<const FieldDescriptor*> sorted_fields( |
||||||
|
SortFieldsByNumber(descriptor_)); |
||||||
|
|
||||||
|
printer->Print( |
||||||
|
"@Override\n" |
||||||
|
"public $classname$ mergeFrom(\n" |
||||||
|
" com.google.protobuf.nano.CodedInputByteBufferNano input)\n" |
||||||
|
" throws java.io.IOException {\n", |
||||||
|
"classname", descriptor_->name()); |
||||||
|
|
||||||
|
printer->Indent(); |
||||||
|
|
||||||
|
printer->Print( |
||||||
|
"while (true) {\n"); |
||||||
|
printer->Indent(); |
||||||
|
|
||||||
|
printer->Print( |
||||||
|
"int tag = input.readTag();\n" |
||||||
|
"switch (tag) {\n"); |
||||||
|
printer->Indent(); |
||||||
|
|
||||||
|
printer->Print( |
||||||
|
"case 0:\n" // zero signals EOF / limit reached
|
||||||
|
" return this;\n" |
||||||
|
"default: {\n" |
||||||
|
" if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n" |
||||||
|
" return this;\n" // it's an endgroup tag
|
||||||
|
" }\n" |
||||||
|
" break;\n" |
||||||
|
"}\n"); |
||||||
|
|
||||||
|
for (int i = 0; i < descriptor_->field_count(); i++) { |
||||||
|
const FieldDescriptor* field = sorted_fields[i]; |
||||||
|
uint32 tag = WireFormatLite::MakeTag(field->number(), |
||||||
|
WireFormat::WireTypeForField(field)); |
||||||
|
|
||||||
|
printer->Print( |
||||||
|
"case $tag$: {\n", |
||||||
|
"tag", SimpleItoa(tag)); |
||||||
|
printer->Indent(); |
||||||
|
|
||||||
|
field_generators_.get(field).GenerateParsingCode(printer); |
||||||
|
|
||||||
|
printer->Outdent(); |
||||||
|
printer->Print( |
||||||
|
" break;\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
|
||||||
|
printer->Outdent(); |
||||||
|
printer->Outdent(); |
||||||
|
printer->Outdent(); |
||||||
|
printer->Print( |
||||||
|
" }\n" // switch (tag)
|
||||||
|
" }\n" // while (true)
|
||||||
|
"}\n" |
||||||
|
"\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void MessageGenerator:: |
||||||
|
GenerateParseFromMethods(io::Printer* printer) { |
||||||
|
bool is_own_file = |
||||||
|
descriptor_->containing_type() == NULL; |
||||||
|
|
||||||
|
// Note: These are separate from GenerateMessageSerializationMethods()
|
||||||
|
// because they need to be generated even for messages that are optimized
|
||||||
|
// for code size.
|
||||||
|
printer->Print( |
||||||
|
"public $static$ $classname$ parseFrom(byte[] data)\n" |
||||||
|
" throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n" |
||||||
|
" return ($classname$) com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n" |
||||||
|
"}\n" |
||||||
|
"\n" |
||||||
|
"public $static$ $classname$ parseFrom(\n" |
||||||
|
" com.google.protobuf.nano.CodedInputByteBufferNano input)\n" |
||||||
|
" throws java.io.IOException {\n" |
||||||
|
" return new $classname$().mergeFrom(input);\n" |
||||||
|
"}\n" |
||||||
|
"\n", |
||||||
|
"static", (is_own_file ? "static" : ""), |
||||||
|
"classname", descriptor_->name()); |
||||||
|
} |
||||||
|
|
||||||
|
void MessageGenerator::GenerateSerializeOneField( |
||||||
|
io::Printer* printer, const FieldDescriptor* field) { |
||||||
|
field_generators_.get(field).GenerateSerializationCode(printer); |
||||||
|
} |
||||||
|
|
||||||
|
void MessageGenerator::GenerateClear(io::Printer* printer) { |
||||||
|
printer->Print( |
||||||
|
"public final $classname$ clear() {\n", |
||||||
|
"classname", descriptor_->name()); |
||||||
|
printer->Indent(); |
||||||
|
|
||||||
|
// Call clear for all of the fields.
|
||||||
|
for (int i = 0; i < descriptor_->field_count(); i++) { |
||||||
|
const FieldDescriptor* field = descriptor_->field(i); |
||||||
|
|
||||||
|
if (field->type() == FieldDescriptor::TYPE_BYTES && |
||||||
|
!field->default_value_string().empty()) { |
||||||
|
// Need to clone the default value because it is of a mutable
|
||||||
|
// type.
|
||||||
|
printer->Print( |
||||||
|
"$name$ = $default$.clone();\n", |
||||||
|
"name", UnderscoresToCamelCase(field), |
||||||
|
"default", DefaultValue(params_, field)); |
||||||
|
} else { |
||||||
|
printer->Print( |
||||||
|
"$name$ = $default$;\n", |
||||||
|
"name", UnderscoresToCamelCase(field), |
||||||
|
"default", DefaultValue(params_, field)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
printer->Outdent(); |
||||||
|
printer->Print( |
||||||
|
" cachedSize = -1;\n" |
||||||
|
" return this;\n" |
||||||
|
"}\n" |
||||||
|
"\n"); |
||||||
|
} |
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,92 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ |
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ |
||||||
|
|
||||||
|
#include <string> |
||||||
|
#include <google/protobuf/stubs/common.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_params.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_field.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace io { |
||||||
|
class Printer; // printer.h
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
class MessageGenerator { |
||||||
|
public: |
||||||
|
explicit MessageGenerator(const Descriptor* descriptor, const Params& params); |
||||||
|
~MessageGenerator(); |
||||||
|
|
||||||
|
// All static variables have to be declared at the top-level of the file
|
||||||
|
// so that we can control initialization order, which is important for
|
||||||
|
// DescriptorProto bootstrapping to work.
|
||||||
|
void GenerateStaticVariables(io::Printer* printer); |
||||||
|
|
||||||
|
// Output code which initializes the static variables generated by
|
||||||
|
// GenerateStaticVariables().
|
||||||
|
void GenerateStaticVariableInitializers(io::Printer* printer); |
||||||
|
|
||||||
|
// Generate the class itself.
|
||||||
|
void Generate(io::Printer* printer); |
||||||
|
|
||||||
|
private: |
||||||
|
void GenerateMessageSerializationMethods(io::Printer* printer); |
||||||
|
void GenerateMergeFromMethods(io::Printer* printer); |
||||||
|
void GenerateParseFromMethods(io::Printer* printer); |
||||||
|
void GenerateSerializeOneField(io::Printer* printer, |
||||||
|
const FieldDescriptor* field); |
||||||
|
|
||||||
|
void GenerateClear(io::Printer* printer); |
||||||
|
|
||||||
|
const Params& params_; |
||||||
|
const Descriptor* descriptor_; |
||||||
|
FieldGeneratorMap field_generators_; |
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
|
@ -0,0 +1,216 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <map> |
||||||
|
#include <string> |
||||||
|
|
||||||
|
#include <google/protobuf/compiler/javanano/javanano_message_field.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_helpers.h> |
||||||
|
#include <google/protobuf/io/printer.h> |
||||||
|
#include <google/protobuf/wire_format.h> |
||||||
|
#include <google/protobuf/stubs/strutil.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
using internal::WireFormat; |
||||||
|
using internal::WireFormatLite; |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
|
||||||
|
// repeat code between this and the other field types.
|
||||||
|
void SetMessageVariables(const Params& params, |
||||||
|
const FieldDescriptor* descriptor, map<string, string>* variables) { |
||||||
|
(*variables)["name"] = |
||||||
|
UnderscoresToCamelCase(descriptor); |
||||||
|
(*variables)["capitalized_name"] = |
||||||
|
UnderscoresToCapitalizedCamelCase(descriptor); |
||||||
|
(*variables)["number"] = SimpleItoa(descriptor->number()); |
||||||
|
(*variables)["type"] = ClassName(params, descriptor->message_type()); |
||||||
|
(*variables)["group_or_message"] = |
||||||
|
(descriptor->type() == FieldDescriptor::TYPE_GROUP) ? |
||||||
|
"Group" : "Message"; |
||||||
|
(*variables)["message_name"] = descriptor->containing_type()->name(); |
||||||
|
//(*variables)["message_type"] = descriptor->message_type()->name();
|
||||||
|
(*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
MessageFieldGenerator:: |
||||||
|
MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params) |
||||||
|
: FieldGenerator(params), descriptor_(descriptor) { |
||||||
|
SetMessageVariables(params, descriptor, &variables_); |
||||||
|
} |
||||||
|
|
||||||
|
MessageFieldGenerator::~MessageFieldGenerator() {} |
||||||
|
|
||||||
|
void MessageFieldGenerator:: |
||||||
|
GenerateMembers(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"public $type$ $name$ = null;\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void MessageFieldGenerator:: |
||||||
|
GenerateMergingCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"if (other.$name$ != null) {\n" |
||||||
|
" merge$capitalized_name$(other.$name$);\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void MessageFieldGenerator:: |
||||||
|
GenerateParsingCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"$name$ = new $type$();\n"); |
||||||
|
|
||||||
|
if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { |
||||||
|
printer->Print(variables_, |
||||||
|
"input.readGroup($name$, $number$);\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"input.readMessage($name$);\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void MessageFieldGenerator:: |
||||||
|
GenerateSerializationCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"if ($name$ != null) {\n" |
||||||
|
" output.write$group_or_message$($number$, $name$);\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void MessageFieldGenerator:: |
||||||
|
GenerateSerializedSizeCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"if ($name$ != null) {\n" |
||||||
|
" size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" |
||||||
|
" .compute$group_or_message$Size($number$, $name$);\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
|
||||||
|
string MessageFieldGenerator::GetBoxedType() const { |
||||||
|
return ClassName(params_, descriptor_->message_type()); |
||||||
|
} |
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
RepeatedMessageFieldGenerator:: |
||||||
|
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params) |
||||||
|
: FieldGenerator(params), descriptor_(descriptor) { |
||||||
|
SetMessageVariables(params, descriptor, &variables_); |
||||||
|
} |
||||||
|
|
||||||
|
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} |
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator:: |
||||||
|
GenerateMembers(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"public $type$[] $name$ = $type$.EMPTY_ARRAY;\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator:: |
||||||
|
GenerateMergingCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"if (other.$name$.length > 0) {\n" |
||||||
|
" $type$[] merged = java.util.Arrays.copyOf(result.$name$, result.$name$.length + other.$name$.length);\n" |
||||||
|
" java.lang.System.arraycopy(other.$name$, 0, merged, results.$name$.length, other.$name$.length);\n" |
||||||
|
" result.$name$ = merged;\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator:: |
||||||
|
GenerateParsingCode(io::Printer* printer) const { |
||||||
|
// First, figure out the length of the array, then parse.
|
||||||
|
printer->Print(variables_, |
||||||
|
"int arrayLength = com.google.protobuf.nano.WireFormatNano.getRepeatedFieldArrayLength(input, $tag$);\n" |
||||||
|
"int i = $name$.length;\n" |
||||||
|
"$name$ = java.util.Arrays.copyOf($name$, i + arrayLength);\n" |
||||||
|
"for (; i < $name$.length - 1; i++) {\n" |
||||||
|
" $name$[i] = new $type$();\n"); |
||||||
|
|
||||||
|
if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { |
||||||
|
printer->Print(variables_, |
||||||
|
" input.readGroup($name$[i], $number$);\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
" input.readMessage($name$[i]);\n"); |
||||||
|
} |
||||||
|
|
||||||
|
printer->Print(variables_, |
||||||
|
" input.readTag();\n" |
||||||
|
"}\n" |
||||||
|
"// Last one without readTag.\n" |
||||||
|
"$name$[i] = new $type$();\n"); |
||||||
|
|
||||||
|
if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { |
||||||
|
printer->Print(variables_, |
||||||
|
"input.readGroup($name$[i], $number$);\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"input.readMessage($name$[i]);\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator:: |
||||||
|
GenerateSerializationCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"for ($type$ element : $name$) {\n" |
||||||
|
" output.write$group_or_message$($number$, element);\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void RepeatedMessageFieldGenerator:: |
||||||
|
GenerateSerializedSizeCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"for ($type$ element : $name$) {\n" |
||||||
|
" size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" |
||||||
|
" .compute$group_or_message$Size($number$, element);\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
|
||||||
|
string RepeatedMessageFieldGenerator::GetBoxedType() const { |
||||||
|
return ClassName(params_, descriptor_->message_type()); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,95 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__ |
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__ |
||||||
|
|
||||||
|
#include <map> |
||||||
|
#include <string> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_field.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
class MessageFieldGenerator : public FieldGenerator { |
||||||
|
public: |
||||||
|
explicit MessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params); |
||||||
|
~MessageFieldGenerator(); |
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GenerateMembers(io::Printer* printer) const; |
||||||
|
void GenerateMergingCode(io::Printer* printer) const; |
||||||
|
void GenerateParsingCode(io::Printer* printer) const; |
||||||
|
void GenerateSerializationCode(io::Printer* printer) const; |
||||||
|
void GenerateSerializedSizeCode(io::Printer* printer) const; |
||||||
|
|
||||||
|
string GetBoxedType() const; |
||||||
|
|
||||||
|
private: |
||||||
|
const FieldDescriptor* descriptor_; |
||||||
|
map<string, string> variables_; |
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); |
||||||
|
}; |
||||||
|
|
||||||
|
class RepeatedMessageFieldGenerator : public FieldGenerator { |
||||||
|
public: |
||||||
|
explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, |
||||||
|
const Params& params); |
||||||
|
~RepeatedMessageFieldGenerator(); |
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GenerateMembers(io::Printer* printer) const; |
||||||
|
void GenerateMergingCode(io::Printer* printer) const; |
||||||
|
void GenerateParsingCode(io::Printer* printer) const; |
||||||
|
void GenerateSerializationCode(io::Printer* printer) const; |
||||||
|
void GenerateSerializedSizeCode(io::Printer* printer) const; |
||||||
|
|
||||||
|
string GetBoxedType() const; |
||||||
|
|
||||||
|
private: |
||||||
|
const FieldDescriptor* descriptor_; |
||||||
|
map<string, string> variables_; |
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
|
@ -0,0 +1,123 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2010 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: wink@google.com (Wink Saville)
|
||||||
|
|
||||||
|
#ifndef PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_ |
||||||
|
#define PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_ |
||||||
|
|
||||||
|
#include <map> |
||||||
|
#include <google/protobuf/stubs/strutil.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
// Parameters for used by the generators
|
||||||
|
class Params { |
||||||
|
public: |
||||||
|
typedef map<string, string> NameMap; |
||||||
|
private: |
||||||
|
string empty_; |
||||||
|
string base_name_; |
||||||
|
bool java_multiple_files_; |
||||||
|
NameMap java_packages_; |
||||||
|
NameMap java_outer_classnames_; |
||||||
|
|
||||||
|
public: |
||||||
|
Params(const string & base_name) : |
||||||
|
empty_(""), |
||||||
|
base_name_(base_name), |
||||||
|
java_multiple_files_(false) { |
||||||
|
} |
||||||
|
|
||||||
|
const string& base_name() const { |
||||||
|
return base_name_; |
||||||
|
} |
||||||
|
|
||||||
|
bool has_java_package(const string& file_name) const { |
||||||
|
return java_packages_.find(file_name) |
||||||
|
!= java_packages_.end(); |
||||||
|
} |
||||||
|
void set_java_package(const string& file_name, |
||||||
|
const string& java_package) { |
||||||
|
java_packages_[file_name] = java_package; |
||||||
|
} |
||||||
|
const string& java_package(const string& file_name) const { |
||||||
|
NameMap::const_iterator itr; |
||||||
|
|
||||||
|
itr = java_packages_.find(file_name); |
||||||
|
if (itr == java_packages_.end()) { |
||||||
|
return empty_; |
||||||
|
} else { |
||||||
|
return itr->second; |
||||||
|
} |
||||||
|
} |
||||||
|
const NameMap& java_packages() { |
||||||
|
return java_packages_; |
||||||
|
} |
||||||
|
|
||||||
|
bool has_java_outer_classname(const string& file_name) const { |
||||||
|
return java_outer_classnames_.find(file_name) |
||||||
|
!= java_outer_classnames_.end(); |
||||||
|
} |
||||||
|
void set_java_outer_classname(const string& file_name, |
||||||
|
const string& java_outer_classname) { |
||||||
|
java_outer_classnames_[file_name] = java_outer_classname; |
||||||
|
} |
||||||
|
const string& java_outer_classname(const string& file_name) const { |
||||||
|
NameMap::const_iterator itr; |
||||||
|
|
||||||
|
itr = java_outer_classnames_.find(file_name); |
||||||
|
if (itr == java_outer_classnames_.end()) { |
||||||
|
return empty_; |
||||||
|
} else { |
||||||
|
return itr->second; |
||||||
|
} |
||||||
|
} |
||||||
|
const NameMap& java_outer_classnames() { |
||||||
|
return java_outer_classnames_; |
||||||
|
} |
||||||
|
|
||||||
|
void set_java_multiple_files(bool value) { |
||||||
|
java_multiple_files_ = value; |
||||||
|
} |
||||||
|
bool java_multiple_files() const { |
||||||
|
return java_multiple_files_; |
||||||
|
} |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
|
#endif // PROTOBUF_COMPILER_JAVANANO_JAVANANO_PARAMS_H_
|
@ -0,0 +1,493 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <map> |
||||||
|
#include <string> |
||||||
|
|
||||||
|
#include <google/protobuf/compiler/javanano/javanano_primitive_field.h> |
||||||
|
#include <google/protobuf/stubs/common.h> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_helpers.h> |
||||||
|
#include <google/protobuf/io/printer.h> |
||||||
|
#include <google/protobuf/wire_format.h> |
||||||
|
#include <google/protobuf/stubs/strutil.h> |
||||||
|
#include <google/protobuf/stubs/substitute.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
using internal::WireFormat; |
||||||
|
using internal::WireFormatLite; |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
const char* PrimitiveTypeName(JavaType type) { |
||||||
|
switch (type) { |
||||||
|
case JAVATYPE_INT : return "int"; |
||||||
|
case JAVATYPE_LONG : return "long"; |
||||||
|
case JAVATYPE_FLOAT : return "float"; |
||||||
|
case JAVATYPE_DOUBLE : return "double"; |
||||||
|
case JAVATYPE_BOOLEAN: return "boolean"; |
||||||
|
case JAVATYPE_STRING : return "java.lang.String"; |
||||||
|
case JAVATYPE_BYTES : return "byte[]"; |
||||||
|
case JAVATYPE_ENUM : return NULL; |
||||||
|
case JAVATYPE_MESSAGE: return NULL; |
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// JavaTypes are added.
|
||||||
|
} |
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
bool IsReferenceType(JavaType type) { |
||||||
|
switch (type) { |
||||||
|
case JAVATYPE_INT : return false; |
||||||
|
case JAVATYPE_LONG : return false; |
||||||
|
case JAVATYPE_FLOAT : return false; |
||||||
|
case JAVATYPE_DOUBLE : return false; |
||||||
|
case JAVATYPE_BOOLEAN: return false; |
||||||
|
case JAVATYPE_STRING : return true; |
||||||
|
case JAVATYPE_BYTES : return true; |
||||||
|
case JAVATYPE_ENUM : return false; |
||||||
|
case JAVATYPE_MESSAGE: return true; |
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// JavaTypes are added.
|
||||||
|
} |
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool IsArrayType(JavaType type) { |
||||||
|
switch (type) { |
||||||
|
case JAVATYPE_INT : return false; |
||||||
|
case JAVATYPE_LONG : return false; |
||||||
|
case JAVATYPE_FLOAT : return false; |
||||||
|
case JAVATYPE_DOUBLE : return false; |
||||||
|
case JAVATYPE_BOOLEAN: return false; |
||||||
|
case JAVATYPE_STRING : return false; |
||||||
|
case JAVATYPE_BYTES : return true; |
||||||
|
case JAVATYPE_ENUM : return false; |
||||||
|
case JAVATYPE_MESSAGE: return false; |
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// JavaTypes are added.
|
||||||
|
} |
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
const char* GetCapitalizedType(const FieldDescriptor* field) { |
||||||
|
switch (field->type()) { |
||||||
|
case FieldDescriptor::TYPE_INT32 : return "Int32" ; |
||||||
|
case FieldDescriptor::TYPE_UINT32 : return "UInt32" ; |
||||||
|
case FieldDescriptor::TYPE_SINT32 : return "SInt32" ; |
||||||
|
case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ; |
||||||
|
case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; |
||||||
|
case FieldDescriptor::TYPE_INT64 : return "Int64" ; |
||||||
|
case FieldDescriptor::TYPE_UINT64 : return "UInt64" ; |
||||||
|
case FieldDescriptor::TYPE_SINT64 : return "SInt64" ; |
||||||
|
case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ; |
||||||
|
case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; |
||||||
|
case FieldDescriptor::TYPE_FLOAT : return "Float" ; |
||||||
|
case FieldDescriptor::TYPE_DOUBLE : return "Double" ; |
||||||
|
case FieldDescriptor::TYPE_BOOL : return "Bool" ; |
||||||
|
case FieldDescriptor::TYPE_STRING : return "String" ; |
||||||
|
case FieldDescriptor::TYPE_BYTES : return "Bytes" ; |
||||||
|
case FieldDescriptor::TYPE_ENUM : return "Enum" ; |
||||||
|
case FieldDescriptor::TYPE_GROUP : return "Group" ; |
||||||
|
case FieldDescriptor::TYPE_MESSAGE : return "Message" ; |
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// types are added.
|
||||||
|
} |
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
// For encodings with fixed sizes, returns that size in bytes. Otherwise
|
||||||
|
// returns -1.
|
||||||
|
int FixedSize(FieldDescriptor::Type type) { |
||||||
|
switch (type) { |
||||||
|
case FieldDescriptor::TYPE_INT32 : return -1; |
||||||
|
case FieldDescriptor::TYPE_INT64 : return -1; |
||||||
|
case FieldDescriptor::TYPE_UINT32 : return -1; |
||||||
|
case FieldDescriptor::TYPE_UINT64 : return -1; |
||||||
|
case FieldDescriptor::TYPE_SINT32 : return -1; |
||||||
|
case FieldDescriptor::TYPE_SINT64 : return -1; |
||||||
|
case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; |
||||||
|
case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; |
||||||
|
case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; |
||||||
|
case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; |
||||||
|
case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; |
||||||
|
case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; |
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; |
||||||
|
case FieldDescriptor::TYPE_ENUM : return -1; |
||||||
|
|
||||||
|
case FieldDescriptor::TYPE_STRING : return -1; |
||||||
|
case FieldDescriptor::TYPE_BYTES : return -1; |
||||||
|
case FieldDescriptor::TYPE_GROUP : return -1; |
||||||
|
case FieldDescriptor::TYPE_MESSAGE : return -1; |
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// types are added.
|
||||||
|
} |
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
// Return true if the type is a that has variable length
|
||||||
|
// for instance String's.
|
||||||
|
bool IsVariableLenType(JavaType type) { |
||||||
|
switch (type) { |
||||||
|
case JAVATYPE_INT : return false; |
||||||
|
case JAVATYPE_LONG : return false; |
||||||
|
case JAVATYPE_FLOAT : return false; |
||||||
|
case JAVATYPE_DOUBLE : return false; |
||||||
|
case JAVATYPE_BOOLEAN: return false; |
||||||
|
case JAVATYPE_STRING : return true; |
||||||
|
case JAVATYPE_BYTES : return true; |
||||||
|
case JAVATYPE_ENUM : return false; |
||||||
|
case JAVATYPE_MESSAGE: return true; |
||||||
|
|
||||||
|
// No default because we want the compiler to complain if any new
|
||||||
|
// JavaTypes are added.
|
||||||
|
} |
||||||
|
|
||||||
|
GOOGLE_LOG(FATAL) << "Can't get here."; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool AllAscii(const string& text) { |
||||||
|
for (int i = 0; i < text.size(); i++) { |
||||||
|
if ((text[i] & 0x80) != 0) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params, |
||||||
|
map<string, string>* variables) { |
||||||
|
(*variables)["name"] = |
||||||
|
UnderscoresToCamelCase(descriptor); |
||||||
|
(*variables)["capitalized_name"] = |
||||||
|
UnderscoresToCapitalizedCamelCase(descriptor); |
||||||
|
(*variables)["number"] = SimpleItoa(descriptor->number()); |
||||||
|
(*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); |
||||||
|
(*variables)["default"] = DefaultValue(params, descriptor); |
||||||
|
(*variables)["default_constant"] = FieldDefaultConstantName(descriptor); |
||||||
|
// For C++-string types (string and bytes), we might need to have
|
||||||
|
// the generated code do the unicode decoding (see comments in
|
||||||
|
// InternalNano.java for gory details.). We would like to do this
|
||||||
|
// once into a "private static final" field and re-use that from
|
||||||
|
// then on.
|
||||||
|
if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING && |
||||||
|
!descriptor->default_value_string().empty()) { |
||||||
|
string default_value; |
||||||
|
if (descriptor->type() == FieldDescriptor::TYPE_BYTES) { |
||||||
|
default_value = strings::Substitute( |
||||||
|
"com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")", |
||||||
|
CEscape(descriptor->default_value_string())); |
||||||
|
} else { |
||||||
|
if (AllAscii(descriptor->default_value_string())) { |
||||||
|
// All chars are ASCII. In this case CEscape() works fine.
|
||||||
|
default_value = "\"" + CEscape(descriptor->default_value_string()) + "\""; |
||||||
|
} else { |
||||||
|
default_value = strings::Substitute( |
||||||
|
"com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")", |
||||||
|
CEscape(descriptor->default_value_string())); |
||||||
|
} |
||||||
|
} |
||||||
|
(*variables)["default_constant_value"] = default_value; |
||||||
|
} |
||||||
|
(*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); |
||||||
|
(*variables)["capitalized_type"] = GetCapitalizedType(descriptor); |
||||||
|
(*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); |
||||||
|
(*variables)["tag_size"] = SimpleItoa( |
||||||
|
WireFormat::TagSize(descriptor->number(), descriptor->type())); |
||||||
|
if (IsReferenceType(GetJavaType(descriptor))) { |
||||||
|
(*variables)["null_check"] = |
||||||
|
" if (value == null) {\n" |
||||||
|
" throw new NullPointerException();\n" |
||||||
|
" }\n"; |
||||||
|
} else { |
||||||
|
(*variables)["null_check"] = ""; |
||||||
|
} |
||||||
|
int fixed_size = FixedSize(descriptor->type()); |
||||||
|
if (fixed_size != -1) { |
||||||
|
(*variables)["fixed_size"] = SimpleItoa(fixed_size); |
||||||
|
} |
||||||
|
(*variables)["message_name"] = descriptor->containing_type()->name(); |
||||||
|
(*variables)["empty_array_name"] = EmptyArrayName(params, descriptor); |
||||||
|
} |
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
PrimitiveFieldGenerator:: |
||||||
|
PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) |
||||||
|
: FieldGenerator(params), descriptor_(descriptor) { |
||||||
|
SetPrimitiveVariables(descriptor, params, &variables_); |
||||||
|
} |
||||||
|
|
||||||
|
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} |
||||||
|
|
||||||
|
void PrimitiveFieldGenerator:: |
||||||
|
GenerateMembers(io::Printer* printer) const { |
||||||
|
if (variables_.find("default_constant_value") != variables_.end()) { |
||||||
|
// Those primitive types that need a saved default.
|
||||||
|
printer->Print(variables_, |
||||||
|
"private static final $type$ $default_constant$ = $default_constant_value$;\n"); |
||||||
|
if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) { |
||||||
|
printer->Print(variables_, |
||||||
|
"public $type$ $name$ = $default$.clone();\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"public $type$ $name$ = $default$;\n"); |
||||||
|
} |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"public $type$ $name$ = $default$;\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void PrimitiveFieldGenerator:: |
||||||
|
GenerateMergingCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, "$name$ = other.$name$;\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void PrimitiveFieldGenerator:: |
||||||
|
GenerateParsingCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"$name$ = input.read$capitalized_type$();\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void PrimitiveFieldGenerator:: |
||||||
|
GenerateSerializationCode(io::Printer* printer) const { |
||||||
|
if (descriptor_->is_required()) { |
||||||
|
printer->Print(variables_, |
||||||
|
"output.write$capitalized_type$($number$, $name$);\n"); |
||||||
|
} else { |
||||||
|
if (IsArrayType(GetJavaType(descriptor_))) { |
||||||
|
printer->Print(variables_, |
||||||
|
"if (!java.util.Arrays.equals($name$, $default$)) {\n"); |
||||||
|
} else if (IsReferenceType(GetJavaType(descriptor_))) { |
||||||
|
printer->Print(variables_, |
||||||
|
"if (!$name$.equals($default$)) {\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"if ($name$ != $default$) {\n"); |
||||||
|
} |
||||||
|
|
||||||
|
printer->Print(variables_, |
||||||
|
" output.write$capitalized_type$($number$, $name$);\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void PrimitiveFieldGenerator:: |
||||||
|
GenerateSerializedSizeCode(io::Printer* printer) const { |
||||||
|
if (descriptor_->is_required()) { |
||||||
|
printer->Print(variables_, |
||||||
|
"size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" |
||||||
|
" .compute$capitalized_type$Size($number$, $name$);\n"); |
||||||
|
} else { |
||||||
|
if (IsArrayType(GetJavaType(descriptor_))) { |
||||||
|
printer->Print(variables_, |
||||||
|
"if (!java.util.Arrays.equals($name$, $default$)) {\n"); |
||||||
|
} else if (IsReferenceType(GetJavaType(descriptor_))) { |
||||||
|
printer->Print(variables_, |
||||||
|
"if (!$name$.equals($default$)) {\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"if ($name$ != $default$) {\n"); |
||||||
|
} |
||||||
|
|
||||||
|
printer->Print(variables_, |
||||||
|
" size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" |
||||||
|
" .compute$capitalized_type$Size($number$, $name$);\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
string PrimitiveFieldGenerator::GetBoxedType() const { |
||||||
|
return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); |
||||||
|
} |
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
RepeatedPrimitiveFieldGenerator:: |
||||||
|
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) |
||||||
|
: FieldGenerator(params), descriptor_(descriptor) { |
||||||
|
SetPrimitiveVariables(descriptor, params, &variables_); |
||||||
|
} |
||||||
|
|
||||||
|
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} |
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator:: |
||||||
|
GenerateMembers(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"public $type$[] $name$ = $default$;\n"); |
||||||
|
if (descriptor_->options().packed()) { |
||||||
|
printer->Print(variables_, |
||||||
|
"private int $name$MemoizedSerializedSize;\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator:: |
||||||
|
GenerateMergingCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"if (other.$name$.length > 0) {\n" |
||||||
|
" $type$[] merged = java.util.Arrays.copyOf(result.$name$, result.$name$.length + other.$name$.length);\n" |
||||||
|
" java.lang.System.arraycopy(other.$name$, 0, merged, results.$name$.length, other.$name$.length);\n" |
||||||
|
" result.$name$ = merged;\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator:: |
||||||
|
GenerateParsingCode(io::Printer* printer) const { |
||||||
|
// First, figure out the length of the array, then parse.
|
||||||
|
if (descriptor_->options().packed()) { |
||||||
|
printer->Print(variables_, |
||||||
|
"int length = input.readRawVarint32();\n" |
||||||
|
"int limit = input.pushLimit(length);\n" |
||||||
|
"// First pass to compute array length.\n" |
||||||
|
"int arrayLength = 0;\n" |
||||||
|
"int startPos = input.getPosition();\n" |
||||||
|
"while (input.getBytesUntilLimit() > 0) {\n" |
||||||
|
" input.read$capitalized_type$();\n" |
||||||
|
" arrayLength++;\n" |
||||||
|
"}\n" |
||||||
|
"input.rewindToPosition(startPos);\n" |
||||||
|
"$name$ = new $type$[arrayLength];\n" |
||||||
|
"for (int i = 0; i < arrayLength; i++) {\n" |
||||||
|
" $name$[i] = input.read$capitalized_type$();\n" |
||||||
|
"}\n" |
||||||
|
"input.popLimit(limit);\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"int arrayLength = com.google.protobuf.nano.WireFormatNano.getRepeatedFieldArrayLength(input, $tag$);\n" |
||||||
|
"int i = $name$.length;\n" |
||||||
|
"$name$ = java.util.Arrays.copyOf($name$, $name$.length + arrayLength);\n" |
||||||
|
"for (; i < $name$.length - 1; i++) {\n" |
||||||
|
" $name$[i] = input.read$capitalized_type$();\n" |
||||||
|
" input.readTag();\n" |
||||||
|
"}\n" |
||||||
|
"// Last one without readTag.\n" |
||||||
|
"$name$[i] = input.read$capitalized_type$();\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator:: |
||||||
|
GenerateSerializationCode(io::Printer* printer) const { |
||||||
|
if (descriptor_->options().packed()) { |
||||||
|
printer->Print(variables_, |
||||||
|
"if ($name$.length > 0) {\n" |
||||||
|
" output.writeRawVarint32($tag$);\n" |
||||||
|
" output.writeRawVarint32($name$MemoizedSerializedSize);\n" |
||||||
|
"}\n"); |
||||||
|
printer->Print(variables_, |
||||||
|
"for ($type$ element : $name$) {\n" |
||||||
|
" output.write$capitalized_type$NoTag(element);\n" |
||||||
|
"}\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"for ($type$ element : $name$) {\n" |
||||||
|
" output.write$capitalized_type$($number$, element);\n" |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void RepeatedPrimitiveFieldGenerator:: |
||||||
|
GenerateSerializedSizeCode(io::Printer* printer) const { |
||||||
|
printer->Print(variables_, |
||||||
|
"if ($name$.length > 0) {\n"); |
||||||
|
printer->Indent(); |
||||||
|
|
||||||
|
if (FixedSize(descriptor_->type()) == -1) { |
||||||
|
printer->Print(variables_, |
||||||
|
"int dataSize = 0;\n" |
||||||
|
"for ($type$ element : $name$) {\n" |
||||||
|
" dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" |
||||||
|
" .compute$capitalized_type$SizeNoTag(element);\n" |
||||||
|
"}\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"int dataSize = $fixed_size$ * $name$.length;\n"); |
||||||
|
} |
||||||
|
|
||||||
|
printer->Print( |
||||||
|
"size += dataSize;\n"); |
||||||
|
if (descriptor_->options().packed()) { |
||||||
|
// cache the data size for packed fields.
|
||||||
|
printer->Print(variables_, |
||||||
|
"size += $tag_size$;\n" |
||||||
|
"size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" |
||||||
|
" .computeRawVarint32Size(dataSize);\n" |
||||||
|
"$name$MemoizedSerializedSize = dataSize;\n"); |
||||||
|
} else { |
||||||
|
printer->Print(variables_, |
||||||
|
"size += $tag_size$ * $name$.length;\n"); |
||||||
|
} |
||||||
|
|
||||||
|
printer->Outdent(); |
||||||
|
|
||||||
|
// set cached size to 0 for empty packed fields.
|
||||||
|
if (descriptor_->options().packed()) { |
||||||
|
printer->Print(variables_, |
||||||
|
"} else {\n" |
||||||
|
" $name$MemoizedSerializedSize = 0;\n" |
||||||
|
"}\n"); |
||||||
|
} else { |
||||||
|
printer->Print( |
||||||
|
"}\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
string RepeatedPrimitiveFieldGenerator::GetBoxedType() const { |
||||||
|
return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,94 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__ |
||||||
|
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__ |
||||||
|
|
||||||
|
#include <map> |
||||||
|
#include <string> |
||||||
|
#include <google/protobuf/compiler/javanano/javanano_field.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
namespace javanano { |
||||||
|
|
||||||
|
class PrimitiveFieldGenerator : public FieldGenerator { |
||||||
|
public: |
||||||
|
explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params ¶ms); |
||||||
|
~PrimitiveFieldGenerator(); |
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GenerateMembers(io::Printer* printer) const; |
||||||
|
void GenerateMergingCode(io::Printer* printer) const; |
||||||
|
void GenerateParsingCode(io::Printer* printer) const; |
||||||
|
void GenerateSerializationCode(io::Printer* printer) const; |
||||||
|
void GenerateSerializedSizeCode(io::Printer* printer) const; |
||||||
|
|
||||||
|
string GetBoxedType() const; |
||||||
|
|
||||||
|
private: |
||||||
|
const FieldDescriptor* descriptor_; |
||||||
|
map<string, string> variables_; |
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); |
||||||
|
}; |
||||||
|
|
||||||
|
class RepeatedPrimitiveFieldGenerator : public FieldGenerator { |
||||||
|
public: |
||||||
|
explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params); |
||||||
|
~RepeatedPrimitiveFieldGenerator(); |
||||||
|
|
||||||
|
// implements FieldGenerator ---------------------------------------
|
||||||
|
void GenerateMembers(io::Printer* printer) const; |
||||||
|
void GenerateMergingCode(io::Printer* printer) const; |
||||||
|
void GenerateParsingCode(io::Printer* printer) const; |
||||||
|
void GenerateSerializationCode(io::Printer* printer) const; |
||||||
|
void GenerateSerializedSizeCode(io::Printer* printer) const; |
||||||
|
|
||||||
|
string GetBoxedType() const; |
||||||
|
|
||||||
|
private: |
||||||
|
const FieldDescriptor* descriptor_; |
||||||
|
map<string, string> variables_; |
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace javanano
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
|
||||||
|
} // namespace google
|
||||||
|
#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_PRIMITIVE_FIELD_H__
|
@ -0,0 +1,49 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// http://code.google.com/p/protobuf/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda) |
||||||
|
// |
||||||
|
// This is like unittest_import.proto but with optimize_for = NANO_RUNTIME. |
||||||
|
|
||||||
|
package protobuf_unittest_import; |
||||||
|
|
||||||
|
// java_package and java_outer_classname are specified on the command line. |
||||||
|
//option java_package = "com.google.protobuf.nano"; |
||||||
|
//option java_outer_classname = "UnittestImportNano"; |
||||||
|
|
||||||
|
message ImportMessageNano { |
||||||
|
optional int32 d = 1; |
||||||
|
} |
||||||
|
|
||||||
|
enum ImportEnumNano { |
||||||
|
IMPORT_NANO_FOO = 7; |
||||||
|
IMPORT_NANO_BAR = 8; |
||||||
|
IMPORT_NANO_BAZ = 9; |
||||||
|
} |
@ -0,0 +1,171 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// http://code.google.com/p/protobuf/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
// Author: wink@google.com (Wink Saville) |
||||||
|
|
||||||
|
package protobuf_unittest; |
||||||
|
|
||||||
|
import "google/protobuf/unittest_import_nano.proto"; |
||||||
|
|
||||||
|
option java_package = "com.google.protobuf.nano"; |
||||||
|
option java_outer_classname = "NanoOuterClass"; |
||||||
|
|
||||||
|
// Same as TestAllTypes but with the nano runtime. |
||||||
|
message TestAllTypesNano { |
||||||
|
|
||||||
|
message NestedMessage { |
||||||
|
optional int32 bb = 1; |
||||||
|
} |
||||||
|
|
||||||
|
enum NestedEnum { |
||||||
|
FOO = 1; |
||||||
|
BAR = 2; |
||||||
|
BAZ = 3; |
||||||
|
} |
||||||
|
|
||||||
|
// Singular |
||||||
|
optional int32 optional_int32 = 1; |
||||||
|
optional int64 optional_int64 = 2; |
||||||
|
optional uint32 optional_uint32 = 3; |
||||||
|
optional uint64 optional_uint64 = 4; |
||||||
|
optional sint32 optional_sint32 = 5; |
||||||
|
optional sint64 optional_sint64 = 6; |
||||||
|
optional fixed32 optional_fixed32 = 7; |
||||||
|
optional fixed64 optional_fixed64 = 8; |
||||||
|
optional sfixed32 optional_sfixed32 = 9; |
||||||
|
optional sfixed64 optional_sfixed64 = 10; |
||||||
|
optional float optional_float = 11; |
||||||
|
optional double optional_double = 12; |
||||||
|
optional bool optional_bool = 13; |
||||||
|
optional string optional_string = 14; |
||||||
|
optional bytes optional_bytes = 15; |
||||||
|
|
||||||
|
optional group OptionalGroup = 16 { |
||||||
|
optional int32 a = 17; |
||||||
|
} |
||||||
|
|
||||||
|
optional NestedMessage optional_nested_message = 18; |
||||||
|
optional ForeignMessageNano optional_foreign_message = 19; |
||||||
|
optional protobuf_unittest_import.ImportMessageNano |
||||||
|
optional_import_message = 20; |
||||||
|
|
||||||
|
optional NestedEnum optional_nested_enum = 21; |
||||||
|
optional ForeignEnumNano optional_foreign_enum = 22; |
||||||
|
optional protobuf_unittest_import.ImportEnumNano optional_import_enum = 23; |
||||||
|
|
||||||
|
optional string optional_string_piece = 24 [ctype=STRING_PIECE]; |
||||||
|
optional string optional_cord = 25 [ctype=CORD]; |
||||||
|
|
||||||
|
// Repeated |
||||||
|
repeated int32 repeated_int32 = 31; |
||||||
|
repeated int64 repeated_int64 = 32; |
||||||
|
repeated uint32 repeated_uint32 = 33; |
||||||
|
repeated uint64 repeated_uint64 = 34; |
||||||
|
repeated sint32 repeated_sint32 = 35; |
||||||
|
repeated sint64 repeated_sint64 = 36; |
||||||
|
repeated fixed32 repeated_fixed32 = 37; |
||||||
|
repeated fixed64 repeated_fixed64 = 38; |
||||||
|
repeated sfixed32 repeated_sfixed32 = 39; |
||||||
|
repeated sfixed64 repeated_sfixed64 = 40; |
||||||
|
repeated float repeated_float = 41; |
||||||
|
repeated double repeated_double = 42; |
||||||
|
repeated bool repeated_bool = 43; |
||||||
|
repeated string repeated_string = 44; |
||||||
|
repeated bytes repeated_bytes = 45; |
||||||
|
|
||||||
|
repeated group RepeatedGroup = 46 { |
||||||
|
optional int32 a = 47; |
||||||
|
} |
||||||
|
|
||||||
|
repeated NestedMessage repeated_nested_message = 48; |
||||||
|
repeated ForeignMessageNano repeated_foreign_message = 49; |
||||||
|
repeated protobuf_unittest_import.ImportMessageNano |
||||||
|
repeated_import_message = 50; |
||||||
|
|
||||||
|
repeated NestedEnum repeated_nested_enum = 51; |
||||||
|
repeated ForeignEnumNano repeated_foreign_enum = 52; |
||||||
|
repeated protobuf_unittest_import.ImportEnumNano repeated_import_enum = 53; |
||||||
|
|
||||||
|
repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; |
||||||
|
repeated string repeated_cord = 55 [ctype=CORD]; |
||||||
|
|
||||||
|
// Repeated packed |
||||||
|
repeated int32 repeated_packed_int32 = 87 [packed=true]; |
||||||
|
repeated sfixed64 repeated_packed_sfixed64 = 88 [packed=true]; |
||||||
|
|
||||||
|
repeated NestedEnum repeated_packed_nested_enum = 89 [packed=true]; |
||||||
|
|
||||||
|
// Singular with defaults |
||||||
|
optional int32 default_int32 = 61 [default = 41 ]; |
||||||
|
optional int64 default_int64 = 62 [default = 42 ]; |
||||||
|
optional uint32 default_uint32 = 63 [default = 43 ]; |
||||||
|
optional uint64 default_uint64 = 64 [default = 44 ]; |
||||||
|
optional sint32 default_sint32 = 65 [default = -45 ]; |
||||||
|
optional sint64 default_sint64 = 66 [default = 46 ]; |
||||||
|
optional fixed32 default_fixed32 = 67 [default = 47 ]; |
||||||
|
optional fixed64 default_fixed64 = 68 [default = 48 ]; |
||||||
|
optional sfixed32 default_sfixed32 = 69 [default = 49 ]; |
||||||
|
optional sfixed64 default_sfixed64 = 70 [default = -50 ]; |
||||||
|
optional float default_float = 71 [default = 51.5 ]; |
||||||
|
optional double default_double = 72 [default = 52e3 ]; |
||||||
|
optional bool default_bool = 73 [default = true ]; |
||||||
|
optional string default_string = 74 [default = "hello"]; |
||||||
|
optional bytes default_bytes = 75 [default = "world"]; |
||||||
|
|
||||||
|
optional string default_string_nonascii = 76 [default = "dünya"]; |
||||||
|
optional bytes default_bytes_nonascii = 77 [default = "dünyab"]; |
||||||
|
|
||||||
|
optional NestedEnum default_nested_enum = 81 [default = BAR]; |
||||||
|
optional ForeignEnumNano default_foreign_enum = 82 |
||||||
|
[default = FOREIGN_NANO_BAR]; |
||||||
|
optional protobuf_unittest_import.ImportEnumNano |
||||||
|
default_import_enum = 83 [default = IMPORT_NANO_BAR]; |
||||||
|
|
||||||
|
optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"]; |
||||||
|
optional string default_cord = 85 [ctype=CORD,default="123"]; |
||||||
|
|
||||||
|
required int32 id = 86; |
||||||
|
} |
||||||
|
|
||||||
|
message ForeignMessageNano { |
||||||
|
optional int32 c = 1; |
||||||
|
} |
||||||
|
|
||||||
|
enum ForeignEnumNano { |
||||||
|
FOREIGN_NANO_FOO = 4; |
||||||
|
FOREIGN_NANO_BAR = 5; |
||||||
|
FOREIGN_NANO_BAZ = 6; |
||||||
|
} |
||||||
|
|
||||||
|
// Test that deprecated fields work. We only verify that they compile (at one |
||||||
|
// point this failed). |
||||||
|
message TestDeprecatedNano { |
||||||
|
optional int32 deprecated_field = 1 [deprecated = true]; |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// http://code.google.com/p/protobuf/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
// Author: wink@google.com (Wink Saville) |
||||||
|
// |
||||||
|
|
||||||
|
package protobuf_unittest_import; |
||||||
|
|
||||||
|
option java_package = "com.google.protobuf.nano"; |
||||||
|
|
||||||
|
message RecursiveMessageNano { |
||||||
|
message NestedMessage { |
||||||
|
optional RecursiveMessageNano a = 1; |
||||||
|
} |
||||||
|
|
||||||
|
required int32 id = 1; |
||||||
|
optional NestedMessage nested_message = 2; |
||||||
|
optional RecursiveMessageNano optional_recursive_message_nano = 3; |
||||||
|
repeated RecursiveMessageNano repeated_recursive_message_nano = 4; |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// http://code.google.com/p/protobuf/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
// Author: wink@google.com (Wink Saville) |
||||||
|
// |
||||||
|
|
||||||
|
package protobuf_unittest_import; |
||||||
|
|
||||||
|
option java_package = "com.google.protobuf.nano"; |
||||||
|
|
||||||
|
message SimpleMessageNano { |
||||||
|
message NestedMessage { |
||||||
|
optional int32 bb = 1; |
||||||
|
} |
||||||
|
|
||||||
|
enum NestedEnum { |
||||||
|
FOO = 1; |
||||||
|
BAR = 2; |
||||||
|
BAZ = 3; |
||||||
|
} |
||||||
|
|
||||||
|
optional int32 d = 1 [default = 123]; |
||||||
|
optional NestedMessage nested_msg = 2; |
||||||
|
optional NestedEnum default_nested_enum = 3 [default = BAZ]; |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// http://code.google.com/p/protobuf/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
// Author: wink@google.com (Wink Saville) |
||||||
|
// |
||||||
|
|
||||||
|
package protobuf_unittest_import; |
||||||
|
|
||||||
|
option java_package = "com.google.protobuf.nano"; |
||||||
|
|
||||||
|
message StringUtf8 { |
||||||
|
optional string id = 1; |
||||||
|
repeated string rs = 2; |
||||||
|
} |
Loading…
Reference in new issue