am 216c9e86: Merge "Nano protobufs."

* commit '216c9e8681b9426e84c9e2222da5c0dd669261b2':
  Nano protobufs.
pull/91/head
Wink Saville 12 years ago committed by Android Git Automerger
commit 08b6e50a9b
  1. 32
      Android.mk
  2. 51
      java/README.txt
  3. 624
      java/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
  4. 910
      java/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
  5. 113
      java/src/main/java/com/google/protobuf/nano/InternalNano.java
  6. 93
      java/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java
  7. 128
      java/src/main/java/com/google/protobuf/nano/MessageNano.java
  8. 138
      java/src/main/java/com/google/protobuf/nano/WireFormatNano.java
  9. 2104
      java/src/test/java/com/google/protobuf/NanoTest.java
  10. 96
      src/google/protobuf/compiler/javanano/javanano_enum.cc
  11. 87
      src/google/protobuf/compiler/javanano/javanano_enum.h
  12. 266
      src/google/protobuf/compiler/javanano/javanano_enum_field.cc
  13. 94
      src/google/protobuf/compiler/javanano/javanano_enum_field.h
  14. 102
      src/google/protobuf/compiler/javanano/javanano_field.cc
  15. 98
      src/google/protobuf/compiler/javanano/javanano_field.h
  16. 251
      src/google/protobuf/compiler/javanano/javanano_file.cc
  17. 94
      src/google/protobuf/compiler/javanano/javanano_file.h
  18. 170
      src/google/protobuf/compiler/javanano/javanano_generator.cc
  19. 72
      src/google/protobuf/compiler/javanano/javanano_generator.h
  20. 404
      src/google/protobuf/compiler/javanano/javanano_helpers.cc
  21. 132
      src/google/protobuf/compiler/javanano/javanano_helpers.h
  22. 372
      src/google/protobuf/compiler/javanano/javanano_message.cc
  23. 92
      src/google/protobuf/compiler/javanano/javanano_message.h
  24. 216
      src/google/protobuf/compiler/javanano/javanano_message_field.cc
  25. 95
      src/google/protobuf/compiler/javanano/javanano_message_field.h
  26. 123
      src/google/protobuf/compiler/javanano/javanano_params.h
  27. 493
      src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
  28. 94
      src/google/protobuf/compiler/javanano/javanano_primitive_field.h
  29. 49
      src/google/protobuf/unittest_import_nano.proto
  30. 171
      src/google/protobuf/unittest_nano.proto
  31. 47
      src/google/protobuf/unittest_recursive_nano.proto
  32. 52
      src/google/protobuf/unittest_simple_nano.proto
  33. 41
      src/google/protobuf/unittest_stringutf8_nano.proto

@ -106,6 +106,15 @@ COMPILER_SRC_FILES := \
src/google/protobuf/compiler/javamicro/javamicro_message.cc \
src/google/protobuf/compiler/javamicro/javamicro_message_field.cc \
src/google/protobuf/compiler/javamicro/javamicro_primitive_field.cc \
src/google/protobuf/compiler/javanano/javanano_enum.cc \
src/google/protobuf/compiler/javanano/javanano_enum_field.cc \
src/google/protobuf/compiler/javanano/javanano_field.cc \
src/google/protobuf/compiler/javanano/javanano_file.cc \
src/google/protobuf/compiler/javanano/javanano_generator.cc \
src/google/protobuf/compiler/javanano/javanano_helpers.cc \
src/google/protobuf/compiler/javanano/javanano_message.cc \
src/google/protobuf/compiler/javanano/javanano_message_field.cc \
src/google/protobuf/compiler/javanano/javanano_primitive_field.cc \
src/google/protobuf/compiler/python/python_generator.cc \
src/google/protobuf/io/coded_stream.cc \
src/google/protobuf/io/gzip_stream.cc \
@ -121,6 +130,29 @@ COMPILER_SRC_FILES := \
src/google/protobuf/stubs/strutil.cc \
src/google/protobuf/stubs/substitute.cc
# Java nano library (for device-side users)
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := libprotobuf-java-2.3.0-nano
LOCAL_MODULE_TAGS := optional
LOCAL_SDK_VERSION := 8
LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/nano)
include $(BUILD_STATIC_JAVA_LIBRARY)
# Java nano library (for host-side users)
# =======================================================
include $(CLEAR_VARS)
LOCAL_MODULE := host-libprotobuf-java-2.3.0-nano
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/nano)
include $(BUILD_HOST_JAVA_LIBRARY)
# Java micro library (for device-side users)
# =======================================================
include $(CLEAR_VARS)

@ -260,6 +260,57 @@ This could be compiled using:
With the result will be com/example/TestMessages.java
Nano version
============================
Nano is even smaller than micro, especially in the number of generated
functions. It is like micro except:
- No setter/getter/hazzer functions.
- Has state is not available. Outputs all fields not equal to their
default. (See important implications below.)
- CodedInputStreamMicro is renamed to CodedInputByteBufferNano and can
only take byte[] (not InputStream).
- Similar rename from CodedOutputStreamMicro to
CodedOutputByteBufferNano.
- Repeated fields are in arrays, not ArrayList or Vector.
- Unset messages/groups are null, not an immutable empty default
instance.
- Required fields are always serialized.
- toByteArray(...) and mergeFrom(...) are now static functions of
MessageNano.
- "bytes" are of java type byte[].
IMPORTANT: If you have fields with defaults
How fields with defaults are serialized has changed. Because we don't
keep "has" state, any field equal to its default is assumed to be not
set and therefore is not serialized. Consider the situation where we
change the default value of a field. Senders compiled against an older
version of the proto continue to match against the old default, and
don't send values to the receiver even though the receiver assumes the
new default value. Therefore, think carefully about the implications
of changing the default value.
IMPORTANT: If you have "bytes" fields with non-empty defaults
Because the byte buffer is now of mutable type byte[], the default
static final cannot be exposed through a public field. Each time a
message's constructor or clear() function is called, the default value
(kept in a private byte[]) is cloned. This causes a small memory
penalty. This is not a problem if the field has no default or is an
empty default.
To use nano protobufs:
- Link with the generated jar file
<protobuf-root>java/target/protobuf-java-2.3.0-nano.jar.
- Invoke with --javanano_out, e.g.:
../src/protoc '--javanano_out=java_package=src/test/proto/simple-data.proto|my_package,java_outer_classname=src/test/proto/simple-data.proto|OuterName:.' src/test/proto/simple-data.proto
Usage
=====

@ -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 &params)
: 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 &params) {
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 &params);
~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 &params);
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 &params);
~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…
Cancel
Save