aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore39
-rw-r--r--Android.mk10
-rw-r--r--README.android16
-rw-r--r--java/README.txt175
-rw-r--r--java/pom.xml57
-rw-r--r--java/src/main/java/com/google/protobuf/micro/ByteStringMicro.java227
-rw-r--r--java/src/main/java/com/google/protobuf/micro/CodedInputStreamMicro.java804
-rw-r--r--java/src/main/java/com/google/protobuf/micro/CodedOutputStreamMicro.java996
-rw-r--r--java/src/main/java/com/google/protobuf/micro/InvalidProtocolBufferMicroException.java93
-rw-r--r--java/src/main/java/com/google/protobuf/micro/MessageMicro.java136
-rw-r--r--java/src/main/java/com/google/protobuf/micro/StringUtf8Micro.java67
-rw-r--r--java/src/main/java/com/google/protobuf/micro/WireFormatMicro.java87
-rw-r--r--java/src/test/java/com/google/protobuf/MicroTest.java2138
-rw-r--r--java/src/test/java/com/google/protobuf/PerfTimer.java832
-rw-r--r--src/Makefile.am18
-rw-r--r--src/Makefile.in97
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_enum.cc96
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_enum.h87
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_enum_field.cc333
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_enum_field.h94
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_field.cc102
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_field.h98
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_file.cc251
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_file.h94
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_generator.cc209
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_generator.h72
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_helpers.cc381
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_helpers.h128
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_message.cc474
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_message.h93
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_message_field.cc302
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_message_field.h95
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_params.h143
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_primitive_field.cc660
-rw-r--r--src/google/protobuf/compiler/javamicro/javamicro_primitive_field.h94
-rw-r--r--src/google/protobuf/compiler/main.cc6
-rw-r--r--src/google/protobuf/unittest_import_micro.proto49
-rw-r--r--src/google/protobuf/unittest_micro.proto162
-rw-r--r--src/google/protobuf/unittest_recursive_micro.proto47
-rw-r--r--src/google/protobuf/unittest_simple_micro.proto52
-rw-r--r--src/google/protobuf/unittest_stringutf8_micro.proto41
41 files changed, 9949 insertions, 6 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4547464
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,39 @@
+# git-ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+*.[oa]
+*~
+*.lo
+*.la
+Makefile
+config.h
+src/Makefile
+/stamp.h1
+.deps
+config.log
+config.status
+gtest/Makefile
+gtest/build-aux/config.h
+gtest/build-aux/stamp-h1
+gtest/libtool
+gtest/scripts/gtest-config
+gtest/lib
+gtest/src/.dirstamp
+protobuf.pc
+protobuf-lite.pc
+libtool
+autom4te.cache/
+/stamp-h1
+core
+src/google/protobuf/unittest*pb*
+src/google/protobuf/compiler/cpp/cpp*pb*
+src/unittest_proto_middleman
+src/protobuf-lazy-descriptor-test
+src/protobuf-lite-test
+src/protobuf-test
+src/zcgunzip
+src/zcgzip
+src/.libs
+src/protoc
+java/target/
diff --git a/Android.mk b/Android.mk
index 9285744..fb2d964 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2010 The Android Open Source Project
+# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -11,8 +11,14 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+#
+#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-# TODO: Add code to build the javamicro library
+LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/micro)
+
+LOCAL_MODULE := com.google.protobuf.micro
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/README.android b/README.android
index a3ff250..2a19787 100644
--- a/README.android
+++ b/README.android
@@ -3,8 +3,8 @@ Version: 2.2.0a
License: Google BSD like
Description: "Protobuf: The Google protobuf compiler and runtimes for various languages"
-Local Modifications: Initial changes include support for the javamicro
-runtime, see java/README.txt for more details.
+Local Modifications: Initial changes include support for the micro
+protobuf compiler and the assoicated runtime.
Protocol Buffers are a way of encoding structured data in an efficient
yet extensible format. Google uses Protocol Buffers for almost all
@@ -12,3 +12,15 @@ of its internal RPC protocols and file formats.
Initially the protoc compiler is not integrated into the Android build system
and the Android.mk will simply build the javamicro runtime static library.
+
+To build the compiler follow the instructions in README.txt for
+compiling and installing.
+
+The Android.mk file creates the a static library which can be added
+to any Android application by Adding to LOCAL_STATIC_JAVA_LIBRARIES
+com.google.protobuf.micro:
+
+ LOCAL_STATIC_JAVA_LIBRARIES += com.google.protobuf.micro
+
+Follow the instructions in Micro section of java/README.txt for
+details on compiling .proto files for the micro runtine.
diff --git a/java/README.txt b/java/README.txt
index 3ed06a1..1656e59 100644
--- a/java/README.txt
+++ b/java/README.txt
@@ -82,11 +82,184 @@ running unit tests.
$ protoc --java_out=src/main/java -I../src \
../src/google/protobuf/descriptor.proto
-
3) Compile the code in src/main/java using whatever means you prefer.
4) Install the classes wherever you prefer.
+Micro version
+============================
+
+The runtime and generated code for MICRO_RUNTIME is smaller
+because it does not include support for the descriptor,
+reflection or extensions. Also, not currently supported
+are packed repeated elements nor testing of java_multiple_files.
+
+To create a jar file for the runtime and run tests invoke
+"mvn package -P micro" from the <protobuf-root>/java
+directory. The generated jar file is
+<protobuf-root>java/target/protobuf-java-2.2.0-micro.jar.
+
+If you wish to compile the MICRO_RUTIME your self, place
+the 7 files below, in <root>/com/google/protobuf and
+create a jar file for use with your code and the generated
+code:
+
+ByteStringMicro.java
+CodedInputStreamMicro.java
+CodedOutputStreamMicro.java
+InvalidProtocolBufferException.java
+MessageMicro.java
+StringUtf8Micro.java
+WireFormatMicro.java
+
+If you wish to change on the code generator it is located
+in /src/google/protobuf/compiler/javamicro.
+
+To generate code for the MICRO_RUNTIME invoke protoc with
+--javamicro_out command line parameter. javamciro_out takes
+a series of optional sub-parameters separated by comma's
+and a final parameter, with a colon separator, which defines
+the source directory. Sub-paraemeters begin with a name
+followed by an equal and if that sub-parameter has multiple
+parameters they are seperated by "|". The command line options
+are:
+
+opt -> speed or space
+java_use_vector -> true or false
+java_package -> <file-name>|<package-name>
+java_outer_classname -> <file-name>|<package-name>
+
+opt:
+ This change the code generation to optimize for speed,
+ opt=speed, or space, opt=space. When opt=speed this
+ changes the code generation for strings to use
+ StringUtf8Micro which eliminates multiple conversions
+ of the string to utf8. The default value is opt=space.
+
+java_use_vector:
+ Is a boolean flag either java_use_vector=true or
+ java_use_vector=false. When java_use_vector=true the
+ code generated for repeated elements uses
+ java.util.Vector and when java_use_vector=false the
+ java.util.ArrayList<> is used. When java.util.Vector
+ is used the code must be compiled with Java 1.3 and
+ when ArrayList is used Java 1.5 or above must be used.
+ The using javac the source parameter maybe used to
+ control the version of the srouce: "javac -source 1.3".
+ You can also change the <source> xml element for the
+ maven-compiler-plugin. Below is for 1.5 sources:
+
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+
+ When compiling for 1.5 java_use_vector=false or not
+ present where the default value is false.
+
+ And below would be for 1.3 sources note when changing
+ to 1.3 you must also set java_use_vector=true:
+
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.3</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+
+java_package:
+ The allows setting/overriding the java_package option
+ and associates allows a package name for a file to
+ be specified on the command line. Overriding any
+ "option java_package xxxx" in the file. The default
+ if not present is to use the value from the package
+ statment or "option java_package xxxx" in the file.
+
+java_outer_classname:
+ This allows the setting/overriding of the outer
+ class name option and associates a class name
+ to a file. An outer class name is required and
+ must be specified if there are multiple messages
+ in a single proto file either in the proto source
+ file or on the command line. If not present the
+ no outer class name will be used.
+
+Below are a series of examples for clarification of the
+various javamicro_out parameters using
+src/test/proto/simple-data.proto:
+
+package testprotobuf;
+
+message SimpleData {
+ optional fixed64 id = 1;
+ optional string description = 2;
+ optional bool ok = 3 [default = false];
+};
+
+
+Assuming you've only compiled and not installed protoc and
+your current working directory java/, then a simple
+command line to compile simple-data would be:
+
+../src/protoc --javamicro_out=. src/test/proto/simple-data.proto
+
+This will create testprotobuf/SimpleData.java
+
+The directory testprotobuf is created because on line 1
+of simple-data.proto is "package testprotobuf;". If you
+wanted a different package name you could use the
+java_package option command line sub-parameter:
+
+../src/protoc '--javamicro_out=java_package=src/test/proto/simple-data.proto|my_package:.' src/test/proto/simple-data.proto
+
+Here you see the new java_package sub-parameter which
+itself needs two parameters the file name and the
+package name, these are separated by "|". Now you'll
+find my_package/SimpleData.java.
+
+If you wanted to also change the optimization for
+speed you'd add opt=speed with the comma seperator
+as follows:
+
+../src/protoc '--javamicro_out=opt=speed,java_package=src/test/proto/simple-data.proto|my_package:.' src/test/proto/simple-data.proto
+
+Finally if you also wanted an outer class name you'd
+do the following:
+
+../src/protoc '--javamicro_out=opt=speed,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
+
+Now you'll find my_packate/OuterName.java.
+
+As mentioned java_package and java_outer_classname
+may also be specified in the file. In the example
+below we must define java_outer_classname because
+there are multiple messages in
+src/test/proto/two-messages.proto
+
+package testmicroruntime;
+
+option java_package = "com.example";
+option java_outer_classname = "TestMessages";
+
+message TestMessage1 {
+ required int32 id = 1;
+}
+
+message TestMessage2 {
+ required int32 id = 1;
+}
+
+This could be compiled using:
+
+../src/protoc --javamicro_out=. src/test/proto/two-message.proto
+
+With the result will be com/example/TestMessages.java
+
+
Usage
=====
diff --git a/java/pom.xml b/java/pom.xml
index 4a35a57..5f7dd17 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -96,6 +96,8 @@
<configuration>
<tasks>
<mkdir dir="target/generated-test-sources" />
+ <!--mkdir dir="target/generated-test-sources/opt-space" /-->
+ <!--mkdir dir="target/generated-test-sources/opt-speed" /-->
<exec executable="../src/protoc">
<arg value="--java_out=target/generated-test-sources" />
<arg value="--proto_path=../src" />
@@ -114,8 +116,20 @@
<arg value="../src/google/protobuf/unittest_lite_imports_nonlite.proto" />
<arg value="../src/google/protobuf/unittest_enormous_descriptor.proto" />
</exec>
+ <exec executable="../src/protoc">
+ <arg value="--javamicro_out=opt=speed,java_use_vector=false,java_package=google/protobuf/unittest_import_micro.proto|com.google.protobuf.micro,java_outer_classname=google/protobuf/unittest_import_micro.proto|UnittestImportMicro:target/generated-test-sources" />
+ <arg value="--proto_path=../src" />
+ <arg value="--proto_path=src/test/java" />
+ <arg value="../src/google/protobuf/unittest_micro.proto" />
+ <arg value="../src/google/protobuf/unittest_simple_micro.proto" />
+ <arg value="../src/google/protobuf/unittest_stringutf8_micro.proto" />
+ <arg value="../src/google/protobuf/unittest_recursive_micro.proto" />
+ <arg value="../src/google/protobuf/unittest_import_micro.proto" />
+ </exec>
</tasks>
<testSourceRoot>target/generated-test-sources</testSourceRoot>
+ <!--testSourceRoot>target/generated-test-sources/opt-space</testSourceRoot-->
+ <!--testSourceRoot>target/generated-test-sources/opt-speed</testSourceRoot-->
</configuration>
<goals>
<goal>run</goal>
@@ -170,5 +184,48 @@
</plugins>
</build>
</profile>
+ <profile>
+ <id>micro</id>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>**/MessageMicro.java</include>
+ <include>**/ByteStringMicro.java</include>
+ <include>**/CodedInputStreamMicro.java</include>
+ <include>**/CodedOutputStreamMicro.java</include>
+ <include>**/InvalidProtocolBufferMicroException.java</include>
+ <include>**/StringUtf8Micro.java</include>
+ <include>**/WireFormatMicro.java</include>
+ </includes>
+ <testIncludes>
+ <testInclude>**/MicroTest.java</testInclude>
+ <testInclude>**/MicroOuterClass.java</testInclude>
+ <testInclude>**/SimpleMessageMicro.java</testInclude>
+ <testInclude>**/StringUtf8.java</testInclude>
+ <testInclude>**/RecursiveMessageMicro.java</testInclude>
+ <testInclude>**/UnittestImportMicro.java</testInclude>
+ </testIncludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>**/MicroTest.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <classifier>micro</classifier>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
</profiles>
</project>
diff --git a/java/src/main/java/com/google/protobuf/micro/ByteStringMicro.java b/java/src/main/java/com/google/protobuf/micro/ByteStringMicro.java
new file mode 100644
index 0000000..6e87dc9
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/micro/ByteStringMicro.java
@@ -0,0 +1,227 @@
+// 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.micro;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Immutable array of bytes.
+ *
+ * @author crazybob@google.com Bob Lee
+ * @author kenton@google.com Kenton Varda
+ */
+public final class ByteStringMicro {
+ private final byte[] bytes;
+
+ private ByteStringMicro(final byte[] bytes) {
+ this.bytes = bytes;
+ }
+
+ /**
+ * Gets the byte at the given index.
+ *
+ * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
+ */
+ public byte byteAt(final int index) {
+ return bytes[index];
+ }
+
+ /**
+ * Gets the number of bytes.
+ */
+ public int size() {
+ return bytes.length;
+ }
+
+ /**
+ * Returns {@code true} if the size is {@code 0}, {@code false} otherwise.
+ */
+ public boolean isEmpty() {
+ return bytes.length == 0;
+ }
+
+ // =================================================================
+ // byte[] -> ByteStringMicro
+
+ /**
+ * Empty ByteStringMicro.
+ */
+ public static final ByteStringMicro EMPTY = new ByteStringMicro(new byte[0]);
+
+ /**
+ * Copies the given bytes into a {@code ByteStringMicro}.
+ */
+ public static ByteStringMicro copyFrom(final byte[] bytes, final int offset,
+ final int size) {
+ final byte[] copy = new byte[size];
+ System.arraycopy(bytes, offset, copy, 0, size);
+ return new ByteStringMicro(copy);
+ }
+
+ /**
+ * Copies the given bytes into a {@code ByteStringMicro}.
+ */
+ public static ByteStringMicro copyFrom(final byte[] bytes) {
+ return copyFrom(bytes, 0, bytes.length);
+ }
+
+ /**
+ * Encodes {@code text} into a sequence of bytes using the named charset
+ * and returns the result as a {@code ByteStringMicro}.
+ */
+ public static ByteStringMicro copyFrom(final String text, final String charsetName)
+ throws UnsupportedEncodingException {
+ return new ByteStringMicro(text.getBytes(charsetName));
+ }
+
+ /**
+ * Encodes {@code text} into a sequence of UTF-8 bytes and returns the
+ * result as a {@code ByteStringMicro}.
+ */
+ public static ByteStringMicro copyFromUtf8(final String text) {
+ try {
+ return new ByteStringMicro(text.getBytes("UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("UTF-8 not supported?");
+ }
+ }
+
+ // =================================================================
+ // ByteStringMicro -> byte[]
+
+ /**
+ * Copies bytes into a buffer at the given offset.
+ *
+ * @param target buffer to copy into
+ * @param offset in the target buffer
+ */
+ public void copyTo(final byte[] target, final int offset) {
+ System.arraycopy(bytes, 0, target, offset, bytes.length);
+ }
+
+ /**
+ * Copies bytes into a buffer.
+ *
+ * @param target buffer to copy into
+ * @param sourceOffset offset within these bytes
+ * @param targetOffset offset within the target buffer
+ * @param size number of bytes to copy
+ */
+ public void copyTo(final byte[] target, final int sourceOffset,
+ final int targetOffset,
+ final int size) {
+ System.arraycopy(bytes, sourceOffset, target, targetOffset, size);
+ }
+
+ /**
+ * Copies bytes to a {@code byte[]}.
+ */
+ public byte[] toByteArray() {
+ final int size = bytes.length;
+ final byte[] copy = new byte[size];
+ System.arraycopy(bytes, 0, copy, 0, size);
+ return copy;
+ }
+
+ /**
+ * Constructs a new {@code String} by decoding the bytes using the
+ * specified charset.
+ */
+ public String toString(final String charsetName)
+ throws UnsupportedEncodingException {
+ return new String(bytes, charsetName);
+ }
+
+ /**
+ * Constructs a new {@code String} by decoding the bytes as UTF-8.
+ */
+ public String toStringUtf8() {
+ try {
+ return new String(bytes, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("UTF-8 not supported?");
+ }
+ }
+
+ // =================================================================
+ // equals() and hashCode()
+
+ //@Override for compatibility with Java 1.3 code we can't use annotations
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+
+ if (!(o instanceof ByteStringMicro)) {
+ return false;
+ }
+
+ final ByteStringMicro other = (ByteStringMicro) o;
+ final int size = bytes.length;
+ if (size != other.bytes.length) {
+ return false;
+ }
+
+ final byte[] thisBytes = bytes;
+ final byte[] otherBytes = other.bytes;
+ for (int i = 0; i < size; i++) {
+ if (thisBytes[i] != otherBytes[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private volatile int hash = 0;
+
+ //@Override for compatibility with Java 1.3 code we can't use annotations
+ public int hashCode() {
+ int h = hash;
+
+ if (h == 0) {
+ final byte[] thisBytes = bytes;
+ final int size = bytes.length;
+
+ h = size;
+ for (int i = 0; i < size; i++) {
+ h = h * 31 + thisBytes[i];
+ }
+ if (h == 0) {
+ h = 1;
+ }
+
+ hash = h;
+ }
+
+ return h;
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/micro/CodedInputStreamMicro.java b/java/src/main/java/com/google/protobuf/micro/CodedInputStreamMicro.java
new file mode 100644
index 0000000..0791b8f
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/micro/CodedInputStreamMicro.java
@@ -0,0 +1,804 @@
+// 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.micro;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * 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 CodedInputStreamMicro {
+ /**
+ * Create a new CodedInputStream wrapping the given InputStream.
+ */
+ public static CodedInputStreamMicro newInstance(final InputStream input) {
+ return new CodedInputStreamMicro(input);
+ }
+
+ /**
+ * Create a new CodedInputStream wrapping the given byte array.
+ */
+ public static CodedInputStreamMicro newInstance(final byte[] buf) {
+ return newInstance(buf, 0, buf.length);
+ }
+
+ /**
+ * Create a new CodedInputStream wrapping the given byte array slice.
+ */
+ public static CodedInputStreamMicro newInstance(final byte[] buf, final int off,
+ final int len) {
+ return new CodedInputStreamMicro(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 InvalidProtocolBufferMicroException.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 InvalidProtocolBufferMicroException {@code value} does not match the
+ * last tag.
+ */
+ public void checkLastTagWas(final int value)
+ throws InvalidProtocolBufferMicroException {
+ if (lastTag != value) {
+ throw InvalidProtocolBufferMicroException.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 (WireFormatMicro.getTagWireType(tag)) {
+ case WireFormatMicro.WIRETYPE_VARINT:
+ readInt32();
+ return true;
+ case WireFormatMicro.WIRETYPE_FIXED64:
+ readRawLittleEndian64();
+ return true;
+ case WireFormatMicro.WIRETYPE_LENGTH_DELIMITED:
+ skipRawBytes(readRawVarint32());
+ return true;
+ case WireFormatMicro.WIRETYPE_START_GROUP:
+ skipMessage();
+ checkLastTagWas(
+ WireFormatMicro.makeTag(WireFormatMicro.getTagFieldNumber(tag),
+ WireFormatMicro.WIRETYPE_END_GROUP));
+ return true;
+ case WireFormatMicro.WIRETYPE_END_GROUP:
+ return false;
+ case WireFormatMicro.WIRETYPE_FIXED32:
+ readRawLittleEndian32();
+ return true;
+ default:
+ throw InvalidProtocolBufferMicroException.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 MessageMicro msg, final int fieldNumber)
+ throws IOException {
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferMicroException.recursionLimitExceeded();
+ }
+ ++recursionDepth;
+ msg.mergeFrom(this);
+ checkLastTagWas(
+ WireFormatMicro.makeTag(fieldNumber, WireFormatMicro.WIRETYPE_END_GROUP));
+ --recursionDepth;
+ }
+
+ public void readMessage(final MessageMicro msg)
+ throws IOException {
+ final int length = readRawVarint32();
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferMicroException.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 ByteStringMicro 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 ByteStringMicro result = ByteStringMicro.copyFrom(buffer, bufferPos, size);
+ bufferPos += size;
+ return result;
+ } else {
+ // Slow path: Build a byte array first then copy it.
+ return ByteStringMicro.copyFrom(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 InvalidProtocolBufferMicroException.malformedVarint();
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Reads a varint from the input one byte at a time, so that it does not
+ * read any bytes after the end of the varint. If you simply wrapped the
+ * stream in a CodedInputStream and used {@link #readRawVarint32(InputStream)}
+ * then you would probably end up reading past the end of the varint since
+ * CodedInputStream buffers its input.
+ */
+ static int readRawVarint32(final InputStream input) throws IOException {
+ int result = 0;
+ int offset = 0;
+ for (; offset < 32; offset += 7) {
+ final int b = input.read();
+ if (b == -1) {
+ throw InvalidProtocolBufferMicroException.truncatedMessage();
+ }
+ result |= (b & 0x7f) << offset;
+ if ((b & 0x80) == 0) {
+ return result;
+ }
+ }
+ // Keep reading up to 64 bits.
+ for (; offset < 64; offset += 7) {
+ final int b = input.read();
+ if (b == -1) {
+ throw InvalidProtocolBufferMicroException.truncatedMessage();
+ }
+ if ((b & 0x80) == 0) {
+ return result;
+ }
+ }
+ throw InvalidProtocolBufferMicroException.malformedVarint();
+ }
+
+ /** 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 InvalidProtocolBufferMicroException.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 bufferSize;
+ private int bufferSizeAfterLimit;
+ private int bufferPos;
+ private final InputStream input;
+ private int lastTag;
+
+ /**
+ * The total number of bytes read before the current buffer. The total
+ * bytes read up to the current position can be computed as
+ * {@code totalBytesRetired + bufferPos}.
+ */
+ private int totalBytesRetired;
+
+ /** 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 static final int BUFFER_SIZE = 4096;
+
+ private CodedInputStreamMicro(final byte[] buffer, final int off, final int len) {
+ this.buffer = buffer;
+ bufferSize = off + len;
+ bufferPos = off;
+ input = null;
+ }
+
+ private CodedInputStreamMicro(final InputStream input) {
+ buffer = new byte[BUFFER_SIZE];
+ bufferSize = 0;
+ bufferPos = 0;
+ this.input = input;
+ }
+
+ /**
+ * 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 (nor with
+ * {@link ByteStringMicro#newCodedInput}).
+ * <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() {
+ totalBytesRetired = 0;
+ }
+
+ /**
+ * 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 InvalidProtocolBufferMicroException {
+ if (byteLimit < 0) {
+ throw InvalidProtocolBufferMicroException.negativeSize();
+ }
+ byteLimit += totalBytesRetired + bufferPos;
+ final int oldLimit = currentLimit;
+ if (byteLimit > oldLimit) {
+ throw InvalidProtocolBufferMicroException.truncatedMessage();
+ }
+ currentLimit = byteLimit;
+
+ recomputeBufferSizeAfterLimit();
+
+ return oldLimit;
+ }
+
+ private void recomputeBufferSizeAfterLimit() {
+ bufferSize += bufferSizeAfterLimit;
+ final int bufferEnd = totalBytesRetired + 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 = totalBytesRetired + 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() throws IOException {
+ return bufferPos == bufferSize && !refillBuffer(false);
+ }
+
+ /**
+ * Called with {@code this.buffer} is empty to read more bytes from the
+ * input. If {@code mustSucceed} is true, refillBuffer() gurantees that
+ * either there will be at least one byte in the buffer when it returns
+ * or it will throw an exception. If {@code mustSucceed} is false,
+ * refillBuffer() returns false if no more bytes were available.
+ */
+ private boolean refillBuffer(final boolean mustSucceed) throws IOException {
+ if (bufferPos < bufferSize) {
+ throw new IllegalStateException(
+ "refillBuffer() called when buffer wasn't empty.");
+ }
+
+ if (totalBytesRetired + bufferSize == currentLimit) {
+ // Oops, we hit a limit.
+ if (mustSucceed) {
+ throw InvalidProtocolBufferMicroException.truncatedMessage();
+ } else {
+ return false;
+ }
+ }
+
+ totalBytesRetired += bufferSize;
+
+ bufferPos = 0;
+ bufferSize = (input == null) ? -1 : input.read(buffer);
+ if (bufferSize == 0 || bufferSize < -1) {
+ throw new IllegalStateException(
+ "InputStream#read(byte[]) returned invalid result: " + bufferSize +
+ "\nThe InputStream implementation is buggy.");
+ }
+ if (bufferSize == -1) {
+ bufferSize = 0;
+ if (mustSucceed) {
+ throw InvalidProtocolBufferMicroException.truncatedMessage();
+ } else {
+ return false;
+ }
+ } else {
+ recomputeBufferSizeAfterLimit();
+ final int totalBytesRead =
+ totalBytesRetired + bufferSize + bufferSizeAfterLimit;
+ if (totalBytesRead > sizeLimit || totalBytesRead < 0) {
+ throw InvalidProtocolBufferMicroException.sizeLimitExceeded();
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Read one byte from the input.
+ *
+ * @throws InvalidProtocolBufferMicroException The end of the stream or the current
+ * limit was reached.
+ */
+ public byte readRawByte() throws IOException {
+ if (bufferPos == bufferSize) {
+ refillBuffer(true);
+ }
+ return buffer[bufferPos++];
+ }
+
+ /**
+ * Read a fixed size of bytes from the input.
+ *
+ * @throws InvalidProtocolBufferMicroException The end of the stream or the current
+ * limit was reached.
+ */
+ public byte[] readRawBytes(final int size) throws IOException {
+ if (size < 0) {
+ throw InvalidProtocolBufferMicroException.negativeSize();
+ }
+
+ if (totalBytesRetired + bufferPos + size > currentLimit) {
+ // Read to the end of the stream anyway.
+ skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
+ // Then fail.
+ throw InvalidProtocolBufferMicroException.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 if (size < BUFFER_SIZE) {
+ // Reading more bytes than are in the buffer, but not an excessive number
+ // of bytes. We can safely allocate the resulting array ahead of time.
+
+ // First copy what we have.
+ final byte[] bytes = new byte[size];
+ int pos = bufferSize - bufferPos;
+ System.arraycopy(buffer, bufferPos, bytes, 0, pos);
+ bufferPos = bufferSize;
+
+ // We want to use refillBuffer() and then copy from the buffer into our
+ // byte array rather than reading directly into our byte array because
+ // the input may be unbuffered.
+ refillBuffer(true);
+
+ while (size - pos > bufferSize) {
+ System.arraycopy(buffer, 0, bytes, pos, bufferSize);
+ pos += bufferSize;
+ bufferPos = bufferSize;
+ refillBuffer(true);
+ }
+
+ System.arraycopy(buffer, 0, bytes, pos, size - pos);
+ bufferPos = size - pos;
+
+ return bytes;
+ } else {
+ // The size is very large. For security reasons, we can't allocate the
+ // entire byte array yet. The size comes directly from the input, so a
+ // maliciously-crafted message could provide a bogus very large size in
+ // order to trick the app into allocating a lot of memory. We avoid this
+ // by allocating and reading only a small chunk at a time, so that the
+ // malicious message must actually *be* extremely large to cause
+ // problems. Meanwhile, we limit the allowed size of a message elsewhere.
+
+ // Remember the buffer markers since we'll have to copy the bytes out of
+ // it later.
+ final int originalBufferPos = bufferPos;
+ final int originalBufferSize = bufferSize;
+
+ // Mark the current buffer consumed.
+ totalBytesRetired += bufferSize;
+ bufferPos = 0;
+ bufferSize = 0;
+
+ // Read all the rest of the bytes we need.
+ int sizeLeft = size - (originalBufferSize - originalBufferPos);
+
+ // For compatibility with Java 1.3 use Vector
+ final java.util.Vector chunks = new java.util.Vector();
+
+ while (sizeLeft > 0) {
+ final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
+ int pos = 0;
+ while (pos < chunk.length) {
+ final int n = (input == null) ? -1 :
+ input.read(chunk, pos, chunk.length - pos);
+ if (n == -1) {
+ throw InvalidProtocolBufferMicroException.truncatedMessage();
+ }
+ totalBytesRetired += n;
+ pos += n;
+ }
+ sizeLeft -= chunk.length;
+ chunks.addElement(chunk);
+ }
+
+ // OK, got everything. Now concatenate it all into one buffer.
+ final byte[] bytes = new byte[size];
+
+ // Start by copying the leftover bytes from this.buffer.
+ int pos = originalBufferSize - originalBufferPos;
+ System.arraycopy(buffer, originalBufferPos, bytes, 0, pos);
+
+ // And now all the chunks.
+ for (int i = 0; i < chunks.size(); i++) {
+ byte [] chunk = (byte [])chunks.elementAt(i);
+ System.arraycopy(chunk, 0, bytes, pos, chunk.length);
+ pos += chunk.length;
+ }
+
+ // Done.
+ return bytes;
+ }
+ }
+
+ /**
+ * Reads and discards {@code size} bytes.
+ *
+ * @throws InvalidProtocolBufferMicroException The end of the stream or the current
+ * limit was reached.
+ */
+ public void skipRawBytes(final int size) throws IOException {
+ if (size < 0) {
+ throw InvalidProtocolBufferMicroException.negativeSize();
+ }
+
+ if (totalBytesRetired + bufferPos + size > currentLimit) {
+ // Read to the end of the stream anyway.
+ skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
+ // Then fail.
+ throw InvalidProtocolBufferMicroException.truncatedMessage();
+ }
+
+ if (size <= bufferSize - bufferPos) {
+ // We have all the bytes we need already.
+ bufferPos += size;
+ } else {
+ // Skipping more bytes than are in the buffer. First skip what we have.
+ int pos = bufferSize - bufferPos;
+ totalBytesRetired += pos;
+ bufferPos = 0;
+ bufferSize = 0;
+
+ // Then skip directly from the InputStream for the rest.
+ while (pos < size) {
+ final int n = (input == null) ? -1 : (int) input.skip(size - pos);
+ if (n <= 0) {
+ throw InvalidProtocolBufferMicroException.truncatedMessage();
+ }
+ pos += n;
+ totalBytesRetired += n;
+ }
+ }
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/micro/CodedOutputStreamMicro.java b/java/src/main/java/com/google/protobuf/micro/CodedOutputStreamMicro.java
new file mode 100644
index 0000000..68b6e97
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/micro/CodedOutputStreamMicro.java
@@ -0,0 +1,996 @@
+// 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.micro;
+
+import java.io.OutputStream;
+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 CodedOutputStreamMicro {
+ private final byte[] buffer;
+ private final int limit;
+ private int position;
+
+ private final OutputStream output;
+
+ /**
+ * The buffer size used in {@link #newInstance(OutputStream)}.
+ */
+ public static final int DEFAULT_BUFFER_SIZE = 4096;
+
+ private CodedOutputStreamMicro(final byte[] buffer, final int offset,
+ final int length) {
+ output = null;
+ this.buffer = buffer;
+ position = offset;
+ limit = offset + length;
+ }
+
+ private CodedOutputStreamMicro(final OutputStream output, final byte[] buffer) {
+ this.output = output;
+ this.buffer = buffer;
+ position = 0;
+ limit = buffer.length;
+ }
+
+ /**
+ * Create a new {@code CodedOutputStream} wrapping the given
+ * {@code OutputStream}.
+ */
+ public static CodedOutputStreamMicro newInstance(final OutputStream output) {
+ return newInstance(output, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * Create a new {@code CodedOutputStream} wrapping the given
+ * {@code OutputStream} with a given buffer size.
+ */
+ public static CodedOutputStreamMicro newInstance(final OutputStream output,
+ final int bufferSize) {
+ return new CodedOutputStreamMicro(output, new byte[bufferSize]);
+ }
+
+ /**
+ * 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 CodedOutputStreamMicro 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 CodedOutputStreamMicro newInstance(final byte[] flatArray,
+ final int offset,
+ final int length) {
+ return new CodedOutputStreamMicro(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, WireFormatMicro.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, WireFormatMicro.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, WireFormatMicro.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, WireFormatMicro.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, WireFormatMicro.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, WireFormatMicro.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, WireFormatMicro.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, WireFormatMicro.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, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED);
+ writeStringNoTag(value);
+ }
+
+ /** Write a {@code StringUtf8Micro} field, including tag, to the stream. */
+ public void writeStringUtf8(final int fieldNumber, final StringUtf8Micro value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED);
+ writeStringUtf8NoTag(value);
+ }
+
+ /** Write a {@code group} field, including tag, to the stream. */
+ public void writeGroup(final int fieldNumber, final MessageMicro value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatMicro.WIRETYPE_START_GROUP);
+ writeGroupNoTag(value);
+ writeTag(fieldNumber, WireFormatMicro.WIRETYPE_END_GROUP);
+ }
+
+ /** Write an embedded message field, including tag, to the stream. */
+ public void writeMessage(final int fieldNumber, final MessageMicro value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value);
+ }
+
+ /** Write a {@code bytes} field, including tag, to the stream. */
+ public void writeBytes(final int fieldNumber, final ByteStringMicro value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED);
+ writeBytesNoTag(value);
+ }
+
+ /** Write a {@code uint32} field, including tag, to the stream. */
+ public void writeUInt32(final int fieldNumber, final int value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormatMicro.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, WireFormatMicro.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, WireFormatMicro.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, WireFormatMicro.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, WireFormatMicro.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, WireFormatMicro.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 StringUtf8Micro} field to the stream. */
+ public void writeStringUtf8NoTag(final StringUtf8Micro value) throws IOException {
+ final byte[] bytes = value.getBytes();
+ writeRawVarint32(bytes.length);
+ writeRawBytes(bytes);
+ }
+
+ /** Write a {@code group} field to the stream. */
+ public void writeGroupNoTag(final MessageMicro value) throws IOException {
+ value.writeTo(this);
+ }
+
+ /** Write an embedded message field to the stream. */
+ public void writeMessageNoTag(final MessageMicro value) throws IOException {
+ writeRawVarint32(value.getCachedSize());
+ value.writeTo(this);
+ }
+
+ /** Write a {@code bytes} field to the stream. */
+ public void writeBytesNoTag(final ByteStringMicro value) throws IOException {
+ final byte[] bytes = value.toByteArray();
+ writeRawVarint32(bytes.length);
+ writeRawBytes(bytes);
+ }
+
+ /** 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 StringUtf8Micro} field, including tag.
+ */
+ public static int computeStringUtf8Size(final int fieldNumber,
+ final StringUtf8Micro value) {
+ return computeTagSize(fieldNumber) + computeStringUtf8SizeNoTag(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 MessageMicro 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 MessageMicro 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 ByteStringMicro value) {
+ return computeTagSize(fieldNumber) + computeBytesSizeNoTag(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 StringUtf8Micro} field.
+ */
+ public static int computeStringUtf8SizeNoTag(final StringUtf8Micro value) {
+ final byte[] bytes = value.getBytes();
+ return computeRawVarint32Size(bytes.length) +
+ bytes.length;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code group} field.
+ */
+ public static int computeGroupSizeNoTag(final MessageMicro value) {
+ return value.getCachedSize();
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an embedded
+ * message field.
+ */
+ public static int computeMessageSizeNoTag(final MessageMicro value) {
+ final int size = value.getCachedSize();
+ return computeRawVarint32Size(size) + size;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bytes} field.
+ */
+ public static int computeBytesSizeNoTag(final ByteStringMicro value) {
+ return computeRawVarint32Size(value.size()) +
+ value.size();
+ }
+
+ /**
+ * 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));
+ }
+
+ // =================================================================
+
+ /**
+ * Internal helper that writes the current buffer to the output. The
+ * buffer position is reset to its initial value when this returns.
+ */
+ private void refreshBuffer() throws IOException {
+ if (output == null) {
+ // We're writing to a single buffer.
+ throw new OutOfSpaceException();
+ }
+
+ // Since we have an output stream, this is our buffer
+ // and buffer offset == 0
+ output.write(buffer, 0, position);
+ position = 0;
+ }
+
+ /**
+ * Flushes the stream and forces any buffered bytes to be written. This
+ * does not flush the underlying OutputStream.
+ */
+ public void flush() throws IOException {
+ if (output != null) {
+ refreshBuffer();
+ }
+ }
+
+ /**
+ * If writing to a flat array, return the space left in the array.
+ * Otherwise, throws {@code UnsupportedOperationException}.
+ */
+ public int spaceLeft() {
+ if (output == null) {
+ return limit - position;
+ } else {
+ throw new UnsupportedOperationException(
+ "spaceLeft() can only be called on CodedOutputStreams that are " +
+ "writing to a flat array.");
+ }
+ }
+
+ /**
+ * 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() {
+ super("CodedOutputStream was writing to a flat byte array and ran " +
+ "out of space.");
+ }
+ }
+
+ /** Write a single byte. */
+ public void writeRawByte(final byte value) throws IOException {
+ if (position == limit) {
+ refreshBuffer();
+ }
+
+ 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 {
+ // Write extends past current buffer. Fill the rest of this buffer and
+ // flush.
+ final int bytesWritten = limit - position;
+ System.arraycopy(value, offset, buffer, position, bytesWritten);
+ offset += bytesWritten;
+ length -= bytesWritten;
+ position = limit;
+ refreshBuffer();
+
+ // Now deal with the rest.
+ // Since we have an output stream, this is our buffer
+ // and buffer offset == 0
+ if (length <= limit) {
+ // Fits in new buffer.
+ System.arraycopy(value, offset, buffer, 0, length);
+ position = length;
+ } else {
+ // Write is very big. Let's do it all at once.
+ output.write(value, offset, length);
+ }
+ }
+ }
+
+ /** Encode and write a tag. */
+ public void writeTag(final int fieldNumber, final int wireType)
+ throws IOException {
+ writeRawVarint32(WireFormatMicro.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(WireFormatMicro.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);
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/micro/InvalidProtocolBufferMicroException.java b/java/src/main/java/com/google/protobuf/micro/InvalidProtocolBufferMicroException.java
new file mode 100644
index 0000000..050f99b
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/micro/InvalidProtocolBufferMicroException.java
@@ -0,0 +1,93 @@
+// 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.micro;
+
+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 InvalidProtocolBufferMicroException extends IOException {
+ private static final long serialVersionUID = -1616151763072450476L;
+
+ public InvalidProtocolBufferMicroException(final String description) {
+ super(description);
+ }
+
+ static InvalidProtocolBufferMicroException truncatedMessage() {
+ return new InvalidProtocolBufferMicroException(
+ "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 InvalidProtocolBufferMicroException negativeSize() {
+ return new InvalidProtocolBufferMicroException(
+ "CodedInputStream encountered an embedded string or message " +
+ "which claimed to have negative size.");
+ }
+
+ static InvalidProtocolBufferMicroException malformedVarint() {
+ return new InvalidProtocolBufferMicroException(
+ "CodedInputStream encountered a malformed varint.");
+ }
+
+ static InvalidProtocolBufferMicroException invalidTag() {
+ return new InvalidProtocolBufferMicroException(
+ "Protocol message contained an invalid tag (zero).");
+ }
+
+ static InvalidProtocolBufferMicroException invalidEndTag() {
+ return new InvalidProtocolBufferMicroException(
+ "Protocol message end-group tag did not match expected tag.");
+ }
+
+ static InvalidProtocolBufferMicroException invalidWireType() {
+ return new InvalidProtocolBufferMicroException(
+ "Protocol message tag had invalid wire type.");
+ }
+
+ static InvalidProtocolBufferMicroException recursionLimitExceeded() {
+ return new InvalidProtocolBufferMicroException(
+ "Protocol message had too many levels of nesting. May be malicious. " +
+ "Use CodedInputStream.setRecursionLimit() to increase the depth limit.");
+ }
+
+ static InvalidProtocolBufferMicroException sizeLimitExceeded() {
+ return new InvalidProtocolBufferMicroException(
+ "Protocol message was too large. May be malicious. " +
+ "Use CodedInputStream.setSizeLimit() to increase the size limit.");
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/micro/MessageMicro.java b/java/src/main/java/com/google/protobuf/micro/MessageMicro.java
new file mode 100644
index 0000000..0c02793
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/micro/MessageMicro.java
@@ -0,0 +1,136 @@
+// 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.micro;
+
+import com.google.protobuf.micro.CodedOutputStreamMicro;
+import java.io.IOException;
+
+/**
+ * Abstract interface implemented by Protocol Message objects.
+ *
+ * @author wink@google.com Wink Saville
+ */
+public abstract class MessageMicro {
+ /**
+ * 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(CodedOutputStreamMicro output) throws java.io.IOException;
+
+ /**
+ * Parse {@code input} as a message of this type and merge it with the
+ * message being built.
+ */
+ abstract public MessageMicro mergeFrom(final CodedInputStreamMicro input) throws IOException;
+
+ /**
+ * Serialize to a byte array.
+ * @return byte array with the serialized data.
+ */
+ public byte[] toByteArray() {
+ final byte[] result = new byte[getSerializedSize()];
+ toByteArray(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 void toByteArray(byte [] data, int offset, int length) {
+ try {
+ final CodedOutputStreamMicro output = CodedOutputStreamMicro.newInstance(data, offset, length);
+ 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 MessageMicro mergeFrom(final byte[] data) throws InvalidProtocolBufferMicroException {
+ return mergeFrom(data, 0, data.length);
+ }
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built.
+ */
+ public MessageMicro mergeFrom(final byte[] data, final int off, final int len)
+ throws InvalidProtocolBufferMicroException {
+ try {
+ final CodedInputStreamMicro input = CodedInputStreamMicro.newInstance(data, off, len);
+ mergeFrom(input);
+ input.checkLastTagWas(0);
+ return this;
+ } catch (InvalidProtocolBufferMicroException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException("Reading from a byte array threw an IOException (should "
+ + "never happen).");
+ }
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ protected boolean parseUnknownField(
+ final CodedInputStreamMicro input,
+ final int tag) throws IOException {
+ return input.skipField(tag);
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/micro/StringUtf8Micro.java b/java/src/main/java/com/google/protobuf/micro/StringUtf8Micro.java
new file mode 100644
index 0000000..0c43e54
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/micro/StringUtf8Micro.java
@@ -0,0 +1,67 @@
+// 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.micro;
+
+/**
+ * A surogate for a String with a UTF8 representation.
+ *
+ * @author wink@google.com Wink Saville
+ */
+public final class StringUtf8Micro {
+ private String string;
+ private byte[] bytes;
+
+ public StringUtf8Micro(String string) {
+ setString(string);
+ }
+
+ public static final StringUtf8Micro EMPTY = new StringUtf8Micro("");
+
+ public String getString() {
+ return string;
+ }
+
+ public void setString(String string) {
+ this.string = string;
+ bytes = null;
+ }
+
+ public byte [] getBytes() {
+ if (bytes == null) {
+ try {
+ bytes = string.getBytes("UTF-8");
+ } catch (java.io.UnsupportedEncodingException e) {
+ throw new RuntimeException("UTF-8 not supported.");
+ }
+ }
+ return bytes;
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/micro/WireFormatMicro.java b/java/src/main/java/com/google/protobuf/micro/WireFormatMicro.java
new file mode 100644
index 0000000..d8a88bd
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/micro/WireFormatMicro.java
@@ -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.
+
+package com.google.protobuf.micro;
+
+/**
+ * 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 WireFormatMicro {
+ // Do not allow instantiation.
+ private WireFormatMicro() {}
+
+ 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);
+}
diff --git a/java/src/test/java/com/google/protobuf/MicroTest.java b/java/src/test/java/com/google/protobuf/MicroTest.java
new file mode 100644
index 0000000..ebfccc2
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/MicroTest.java
@@ -0,0 +1,2138 @@
+// 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;
+
+import com.google.protobuf.micro.MicroOuterClass;
+import com.google.protobuf.micro.MicroOuterClass.TestAllTypesMicro;
+import com.google.protobuf.micro.RecursiveMessageMicro;
+import com.google.protobuf.micro.SimpleMessageMicro;
+import com.google.protobuf.micro.StringUtf8;
+import com.google.protobuf.micro.StringUtf8Micro;
+import com.google.protobuf.micro.UnittestImportMicro;
+import com.google.protobuf.micro.ByteStringMicro;
+
+import junit.framework.TestCase;
+
+/**
+ * Test micro runtime.
+ *
+ * @author wink@google.com Wink Saville
+ */
+public class MicroTest extends TestCase {
+ public void setUp() throws Exception {
+ }
+
+ public void testSimpleMessageMicro() throws Exception {
+ SimpleMessageMicro msg = new SimpleMessageMicro();
+ assertFalse(msg.hasD());
+ assertEquals(123, msg.getD());
+ assertFalse(msg.hasNestedMsg());
+ assertEquals(null, msg.getNestedMsg());
+ assertFalse(msg.hasDefaultNestedEnum());
+ assertEquals(SimpleMessageMicro.BAZ, msg.getDefaultNestedEnum());
+
+ msg.setD(456);
+ assertTrue(msg.hasD());
+ assertEquals(456, msg.getD());
+ msg.clearD()
+ .setD(456);
+ assertTrue(msg.hasD());
+
+ SimpleMessageMicro.NestedMessage nestedMsg = new SimpleMessageMicro.NestedMessage()
+ .setBb(2);
+ assertTrue(nestedMsg.hasBb());
+ assertEquals(2, nestedMsg.getBb());
+ msg.setNestedMsg(nestedMsg);
+ assertTrue(msg.hasNestedMsg());
+ assertEquals(2, msg.getNestedMsg().getBb());
+
+ msg.setDefaultNestedEnum(SimpleMessageMicro.BAR);
+ assertTrue(msg.hasDefaultNestedEnum());
+ assertEquals(SimpleMessageMicro.BAR, msg.getDefaultNestedEnum());
+
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+
+ SimpleMessageMicro newMsg = SimpleMessageMicro.parseFrom(result);
+ assertTrue(newMsg.hasD());
+ assertTrue(newMsg.hasNestedMsg());
+ assertTrue(newMsg.hasDefaultNestedEnum());
+ assertEquals(456, newMsg.getD());
+ assertEquals(2, msg.getNestedMsg().getBb());
+ assertEquals(SimpleMessageMicro.BAR, msg.getDefaultNestedEnum());
+ }
+
+ public void testRecursiveMessageMicro() throws Exception {
+ RecursiveMessageMicro msg = new RecursiveMessageMicro();
+ assertFalse(msg.hasId());
+ assertFalse(msg.hasNestedMessage());
+ assertFalse(msg.hasOptionalRecursiveMessageMicro());
+ assertEquals(0, msg.getRepeatedRecursiveMessageMicroCount());
+
+ RecursiveMessageMicro msg1 = new RecursiveMessageMicro();
+ msg1.setId(1);
+ assertEquals(1, msg1.getId());
+ RecursiveMessageMicro msg2 = new RecursiveMessageMicro();
+ msg2.setId(2);
+ RecursiveMessageMicro msg3 = new RecursiveMessageMicro();
+ msg3.setId(3);
+
+ RecursiveMessageMicro.NestedMessage nestedMsg = new RecursiveMessageMicro.NestedMessage();
+ nestedMsg.setA(msg1);
+ assertEquals(1, nestedMsg.getA().getId());
+
+ msg.setId(0);
+ msg.setNestedMessage(nestedMsg);
+ msg.setOptionalRecursiveMessageMicro(msg2);
+ msg.addRepeatedRecursiveMessageMicro(msg3);
+
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 16);
+ assertEquals(result.length, msgSerializedSize);
+
+ RecursiveMessageMicro newMsg = RecursiveMessageMicro.parseFrom(result);
+ assertTrue(newMsg.hasId());
+ assertTrue(newMsg.hasNestedMessage());
+ assertTrue(newMsg.hasOptionalRecursiveMessageMicro());
+ assertEquals(1, newMsg.getRepeatedRecursiveMessageMicroCount());
+
+ assertEquals(0, newMsg.getId());
+ assertEquals(1, newMsg.getNestedMessage().getA().getId());
+ assertEquals(2, newMsg.getOptionalRecursiveMessageMicro().getId());
+ assertEquals(3, newMsg.getRepeatedRecursiveMessageMicro(0).getId());
+ }
+
+ public void testMicroRequiredInt32() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasId());
+ assertFalse(msg.isInitialized());
+ msg.setId(123);
+ assertTrue(msg.hasId());
+ assertTrue(msg.isInitialized());
+ assertEquals(123, msg.getId());
+ msg.clearId();
+ assertFalse(msg.hasId());
+ assertFalse(msg.isInitialized());
+ msg.clearId()
+ .setId(456);
+ assertTrue(msg.hasId());
+ msg.clear();
+ assertFalse(msg.hasId());
+ assertFalse(msg.isInitialized());
+
+ msg.setId(123);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasId());
+ assertTrue(newMsg.isInitialized());
+ assertEquals(123, newMsg.getId());
+ }
+
+ public void testMicroOptionalInt32() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalInt32());
+ msg.setOptionalInt32(123);
+ assertTrue(msg.hasOptionalInt32());
+ assertEquals(123, msg.getOptionalInt32());
+ msg.clearOptionalInt32();
+ assertFalse(msg.hasOptionalInt32());
+ msg.clearOptionalInt32()
+ .setOptionalInt32(456);
+ assertTrue(msg.hasOptionalInt32());
+ msg.clear();
+ assertFalse(msg.hasOptionalInt32());
+
+ msg.setOptionalInt32(123);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 2);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalInt32());
+ assertEquals(123, newMsg.getOptionalInt32());
+ }
+
+ public void testMicroOptionalInt64() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalInt64());
+ msg.setOptionalInt64(123);
+ assertTrue(msg.hasOptionalInt64());
+ assertEquals(123, msg.getOptionalInt64());
+ msg.clearOptionalInt64();
+ assertFalse(msg.hasOptionalInt64());
+ msg.clearOptionalInt64()
+ .setOptionalInt64(456);
+ assertTrue(msg.hasOptionalInt64());
+ msg.clear();
+ assertFalse(msg.hasOptionalInt64());
+
+ msg.setOptionalInt64(123);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 2);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalInt64());
+ assertEquals(123, newMsg.getOptionalInt64());
+ }
+
+ public void testMicroOptionalUint32() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalUint32());
+ msg.setOptionalUint32(123);
+ assertTrue(msg.hasOptionalUint32());
+ assertEquals(123, msg.getOptionalUint32());
+ msg.clearOptionalUint32();
+ assertFalse(msg.hasOptionalUint32());
+ msg.clearOptionalUint32()
+ .setOptionalUint32(456);
+ assertTrue(msg.hasOptionalUint32());
+ msg.clear();
+ assertFalse(msg.hasOptionalUint32());
+
+ msg.setOptionalUint32(123);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 2);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalUint32());
+ assertEquals(123, newMsg.getOptionalUint32());
+ }
+
+ public void testMicroOptionalUint64() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalUint64());
+ msg.setOptionalUint64(123);
+ assertTrue(msg.hasOptionalUint64());
+ assertEquals(123, msg.getOptionalUint64());
+ msg.clearOptionalUint64();
+ assertFalse(msg.hasOptionalUint64());
+ msg.clearOptionalUint64()
+ .setOptionalUint64(456);
+ assertTrue(msg.hasOptionalUint64());
+ msg.clear();
+ assertFalse(msg.hasOptionalUint64());
+
+ msg.setOptionalUint64(123);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 2);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalUint64());
+ assertEquals(123, newMsg.getOptionalUint64());
+ }
+
+ public void testMicroOptionalSint32() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalSint32());
+ msg.setOptionalSint32(123);
+ assertTrue(msg.hasOptionalSint32());
+ assertEquals(123, msg.getOptionalSint32());
+ msg.clearOptionalSint32();
+ assertFalse(msg.hasOptionalSint32());
+ msg.clearOptionalSint32()
+ .setOptionalSint32(456);
+ assertTrue(msg.hasOptionalSint32());
+ msg.clear();
+ assertFalse(msg.hasOptionalSint32());
+
+ msg.setOptionalSint32(-123);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalSint32());
+ assertEquals(-123, newMsg.getOptionalSint32());
+ }
+
+ public void testMicroOptionalSint64() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalSint64());
+ msg.setOptionalSint64(123);
+ assertTrue(msg.hasOptionalSint64());
+ assertEquals(123, msg.getOptionalSint64());
+ msg.clearOptionalSint64();
+ assertFalse(msg.hasOptionalSint64());
+ msg.clearOptionalSint64()
+ .setOptionalSint64(456);
+ assertTrue(msg.hasOptionalSint64());
+ msg.clear();
+ assertFalse(msg.hasOptionalSint64());
+
+ msg.setOptionalSint64(-123);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalSint64());
+ assertEquals(-123, newMsg.getOptionalSint64());
+ }
+
+ public void testMicroOptionalFixed32() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalFixed32());
+ msg.setOptionalFixed32(123);
+ assertTrue(msg.hasOptionalFixed32());
+ assertEquals(123, msg.getOptionalFixed32());
+ msg.clearOptionalFixed32();
+ assertFalse(msg.hasOptionalFixed32());
+ msg.clearOptionalFixed32()
+ .setOptionalFixed32(456);
+ assertTrue(msg.hasOptionalFixed32());
+ msg.clear();
+ assertFalse(msg.hasOptionalFixed32());
+
+ msg.setOptionalFixed32(123);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalFixed32());
+ assertEquals(123, newMsg.getOptionalFixed32());
+ }
+
+ public void testMicroOptionalFixed64() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalFixed64());
+ msg.setOptionalFixed64(123);
+ assertTrue(msg.hasOptionalFixed64());
+ assertEquals(123, msg.getOptionalFixed64());
+ msg.clearOptionalFixed64();
+ assertFalse(msg.hasOptionalFixed64());
+ msg.clearOptionalFixed64()
+ .setOptionalFixed64(456);
+ assertTrue(msg.hasOptionalFixed64());
+ msg.clear();
+ assertFalse(msg.hasOptionalFixed64());
+
+ msg.setOptionalFixed64(123);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalFixed64());
+ assertEquals(123, newMsg.getOptionalFixed64());
+ }
+ public void testMicroOptionalSfixed32() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalSfixed32());
+ msg.setOptionalSfixed32(123);
+ assertTrue(msg.hasOptionalSfixed32());
+ assertEquals(123, msg.getOptionalSfixed32());
+ msg.clearOptionalSfixed32();
+ assertFalse(msg.hasOptionalSfixed32());
+ msg.clearOptionalSfixed32()
+ .setOptionalSfixed32(456);
+ assertTrue(msg.hasOptionalSfixed32());
+ msg.clear();
+ assertFalse(msg.hasOptionalSfixed32());
+
+ msg.setOptionalSfixed32(123);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalSfixed32());
+ assertEquals(123, newMsg.getOptionalSfixed32());
+ }
+
+ public void testMicroOptionalSfixed64() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalSfixed64());
+ msg.setOptionalSfixed64(123);
+ assertTrue(msg.hasOptionalSfixed64());
+ assertEquals(123, msg.getOptionalSfixed64());
+ msg.clearOptionalSfixed64();
+ assertFalse(msg.hasOptionalSfixed64());
+ msg.clearOptionalSfixed64()
+ .setOptionalSfixed64(456);
+ assertTrue(msg.hasOptionalSfixed64());
+ msg.clear();
+ assertFalse(msg.hasOptionalSfixed64());
+
+ msg.setOptionalSfixed64(-123);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalSfixed64());
+ assertEquals(-123, newMsg.getOptionalSfixed64());
+ }
+
+ public void testMicroOptionalFloat() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalFloat());
+ msg.setOptionalFloat(123f);
+ assertTrue(msg.hasOptionalFloat());
+ assertTrue(123.0f == msg.getOptionalFloat());
+ msg.clearOptionalFloat();
+ assertFalse(msg.hasOptionalFloat());
+ msg.clearOptionalFloat()
+ .setOptionalFloat(456.0f);
+ assertTrue(msg.hasOptionalFloat());
+ msg.clear();
+ assertFalse(msg.hasOptionalFloat());
+
+ msg.setOptionalFloat(-123.456f);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalFloat());
+ assertTrue(-123.456f == newMsg.getOptionalFloat());
+ }
+
+ public void testMicroOptionalDouble() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalDouble());
+ msg.setOptionalDouble(123);
+ assertTrue(msg.hasOptionalDouble());
+ assertTrue(123.0 == msg.getOptionalDouble());
+ msg.clearOptionalDouble();
+ assertFalse(msg.hasOptionalDouble());
+ msg.clearOptionalDouble()
+ .setOptionalDouble(456.0);
+ assertTrue(msg.hasOptionalDouble());
+ msg.clear();
+ assertFalse(msg.hasOptionalDouble());
+
+ msg.setOptionalDouble(-123.456);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 9);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalDouble());
+ assertTrue(-123.456 == newMsg.getOptionalDouble());
+ }
+
+ public void testMicroOptionalBool() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalBool());
+ msg.setOptionalBool(true);
+ assertTrue(msg.hasOptionalBool());
+ assertEquals(true, msg.getOptionalBool());
+ msg.clearOptionalBool();
+ assertFalse(msg.hasOptionalBool());
+ msg.clearOptionalBool()
+ .setOptionalBool(true);
+ assertTrue(msg.hasOptionalBool());
+ msg.clear();
+ assertFalse(msg.hasOptionalBool());
+
+ msg.setOptionalBool(false);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 2);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalBool());
+ assertEquals(false, newMsg.getOptionalBool());
+ }
+
+ public void testMicroOptionalString() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalString());
+ msg.setOptionalString("hello");
+ assertTrue(msg.hasOptionalString());
+ assertEquals("hello", msg.getOptionalString());
+ msg.clearOptionalString();
+ assertFalse(msg.hasOptionalString());
+ msg.clearOptionalString()
+ .setOptionalString("hello");
+ assertTrue(msg.hasOptionalString());
+ msg.clear();
+ assertFalse(msg.hasOptionalString());
+
+ msg.setOptionalString("bye");
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalString());
+ assertEquals("bye", newMsg.getOptionalString());
+ }
+
+ public void testMicroOptionalBytes() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalBytes());
+ msg.setOptionalBytes(ByteStringMicro.copyFromUtf8("hello"));
+ assertTrue(msg.hasOptionalBytes());
+ assertEquals("hello", msg.getOptionalBytes().toStringUtf8());
+ msg.clearOptionalBytes();
+ assertFalse(msg.hasOptionalBytes());
+ msg.clearOptionalBytes()
+ .setOptionalBytes(ByteStringMicro.copyFromUtf8("hello"));
+ assertTrue(msg.hasOptionalBytes());
+ msg.clear();
+ assertFalse(msg.hasOptionalBytes());
+
+ msg.setOptionalBytes(ByteStringMicro.copyFromUtf8("bye"));
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalBytes());
+ assertEquals("bye", newMsg.getOptionalBytes().toStringUtf8());
+ }
+
+ public void testMicroOptionalGroup() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ TestAllTypesMicro.OptionalGroup grp = new TestAllTypesMicro.OptionalGroup();
+ grp.setA(1);
+ assertFalse(msg.hasOptionalGroup());
+ msg.setOptionalGroup(grp);
+ assertTrue(msg.hasOptionalGroup());
+ assertEquals(1, msg.getOptionalGroup().getA());
+ msg.clearOptionalGroup();
+ assertFalse(msg.hasOptionalGroup());
+ msg.clearOptionalGroup()
+ .setOptionalGroup(new TestAllTypesMicro.OptionalGroup().setA(2));
+ assertTrue(msg.hasOptionalGroup());
+ msg.clear();
+ assertFalse(msg.hasOptionalGroup());
+
+ msg.setOptionalGroup(grp);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 7);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalGroup());
+ assertEquals(1, newMsg.getOptionalGroup().getA());
+ }
+
+ public void testMicroOptionalNestedMessage() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ TestAllTypesMicro.NestedMessage nestedMsg = new TestAllTypesMicro.NestedMessage();
+ nestedMsg.setBb(1);
+ assertFalse(msg.hasOptionalNestedMessage());
+ msg.setOptionalNestedMessage(nestedMsg);
+ assertTrue(msg.hasOptionalNestedMessage());
+ assertEquals(1, msg.getOptionalNestedMessage().getBb());
+ msg.clearOptionalNestedMessage();
+ assertFalse(msg.hasOptionalNestedMessage());
+ msg.clearOptionalNestedMessage()
+ .setOptionalNestedMessage(new TestAllTypesMicro.NestedMessage().setBb(2));
+ assertTrue(msg.hasOptionalNestedMessage());
+ msg.clear();
+ assertFalse(msg.hasOptionalNestedMessage());
+
+ msg.setOptionalNestedMessage(nestedMsg);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalNestedMessage());
+ assertEquals(1, newMsg.getOptionalNestedMessage().getBb());
+ }
+
+ public void testMicroOptionalForeignMessage() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ MicroOuterClass.ForeignMessageMicro foreignMsg =
+ new MicroOuterClass.ForeignMessageMicro();
+ assertFalse(foreignMsg.hasC());
+ foreignMsg.setC(1);
+ assertTrue(foreignMsg.hasC());
+ assertFalse(msg.hasOptionalForeignMessage());
+ msg.setOptionalForeignMessage(foreignMsg);
+ assertTrue(msg.hasOptionalForeignMessage());
+ assertEquals(1, msg.getOptionalForeignMessage().getC());
+ msg.clearOptionalForeignMessage();
+ assertFalse(msg.hasOptionalForeignMessage());
+ msg.clearOptionalForeignMessage()
+ .setOptionalForeignMessage(new MicroOuterClass.ForeignMessageMicro().setC(2));
+ assertTrue(msg.hasOptionalForeignMessage());
+ msg.clear();
+ assertFalse(msg.hasOptionalForeignMessage());
+
+ msg.setOptionalForeignMessage(foreignMsg);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalForeignMessage());
+ assertEquals(1, newMsg.getOptionalForeignMessage().getC());
+ }
+
+ public void testMicroOptionalImportMessage() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ UnittestImportMicro.ImportMessageMicro importMsg =
+ new UnittestImportMicro.ImportMessageMicro();
+ assertFalse(importMsg.hasD());
+ importMsg.setD(1);
+ assertTrue(importMsg.hasD());
+ assertFalse(msg.hasOptionalImportMessage());
+ msg.setOptionalImportMessage(importMsg);
+ assertTrue(msg.hasOptionalImportMessage());
+ assertEquals(1, msg.getOptionalImportMessage().getD());
+ msg.clearOptionalImportMessage();
+ assertFalse(msg.hasOptionalImportMessage());
+ msg.clearOptionalImportMessage()
+ .setOptionalImportMessage(new UnittestImportMicro.ImportMessageMicro().setD(2));
+ assertTrue(msg.hasOptionalImportMessage());
+ msg.clear();
+ assertFalse(msg.hasOptionalImportMessage());
+
+ msg.setOptionalImportMessage(importMsg);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalImportMessage());
+ assertEquals(1, newMsg.getOptionalImportMessage().getD());
+ }
+
+ public void testMicroOptionalNestedEnum() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ msg.setOptionalNestedEnum(TestAllTypesMicro.BAR);
+ assertTrue(msg.hasOptionalNestedEnum());
+ assertEquals(TestAllTypesMicro.BAR, msg.getOptionalNestedEnum());
+ msg.clearOptionalNestedEnum();
+ assertFalse(msg.hasOptionalNestedEnum());
+ msg.clearOptionalNestedEnum()
+ .setOptionalNestedEnum(TestAllTypesMicro.BAZ);
+ assertTrue(msg.hasOptionalNestedEnum());
+ msg.clear();
+ assertFalse(msg.hasOptionalNestedEnum());
+
+ msg.setOptionalNestedEnum(TestAllTypesMicro.BAR);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalNestedEnum());
+ assertEquals(TestAllTypesMicro.BAR, newMsg.getOptionalNestedEnum());
+ }
+
+ public void testMicroOptionalForeignEnum() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ msg.setOptionalForeignEnum(MicroOuterClass.FOREIGN_MICRO_BAR);
+ assertTrue(msg.hasOptionalForeignEnum());
+ assertEquals(MicroOuterClass.FOREIGN_MICRO_BAR,
+ msg.getOptionalForeignEnum());
+ msg.clearOptionalForeignEnum();
+ assertFalse(msg.hasOptionalForeignEnum());
+ msg.clearOptionalForeignEnum()
+ .setOptionalForeignEnum(MicroOuterClass.FOREIGN_MICRO_BAZ);
+ assertTrue(msg.hasOptionalForeignEnum());
+ msg.clear();
+ assertFalse(msg.hasOptionalForeignEnum());
+
+ msg.setOptionalForeignEnum(MicroOuterClass.FOREIGN_MICRO_BAR);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalForeignEnum());
+ assertEquals(MicroOuterClass.FOREIGN_MICRO_BAR,
+ newMsg.getOptionalForeignEnum());
+ }
+
+ public void testMicroOptionalImportEnum() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ msg.setOptionalImportEnum(UnittestImportMicro.IMPORT_MICRO_BAR);
+ assertTrue(msg.hasOptionalImportEnum());
+ assertEquals(UnittestImportMicro.IMPORT_MICRO_BAR,
+ msg.getOptionalImportEnum());
+ msg.clearOptionalImportEnum();
+ assertFalse(msg.hasOptionalImportEnum());
+ msg.clearOptionalImportEnum()
+ .setOptionalImportEnum(UnittestImportMicro.IMPORT_MICRO_BAZ);
+ assertTrue(msg.hasOptionalImportEnum());
+ msg.clear();
+ assertFalse(msg.hasOptionalImportEnum());
+
+ msg.setOptionalImportEnum(UnittestImportMicro.IMPORT_MICRO_BAR);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalImportEnum());
+ assertEquals(UnittestImportMicro.IMPORT_MICRO_BAR,
+ newMsg.getOptionalImportEnum());
+ }
+
+ public void testMicroOptionalStringPiece() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalStringPiece());
+ msg.setOptionalStringPiece("hello");
+ assertTrue(msg.hasOptionalStringPiece());
+ assertEquals("hello", msg.getOptionalStringPiece());
+ msg.clearOptionalStringPiece();
+ assertFalse(msg.hasOptionalStringPiece());
+ msg.clearOptionalStringPiece()
+ .setOptionalStringPiece("hello");
+ assertTrue(msg.hasOptionalStringPiece());
+ msg.clear();
+ assertFalse(msg.hasOptionalStringPiece());
+
+ msg.setOptionalStringPiece("bye");
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalStringPiece());
+ assertEquals("bye", newMsg.getOptionalStringPiece());
+ }
+
+ public void testMicroOptionalCord() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasOptionalCord());
+ msg.setOptionalCord("hello");
+ assertTrue(msg.hasOptionalCord());
+ assertEquals("hello", msg.getOptionalCord());
+ msg.clearOptionalCord();
+ assertFalse(msg.hasOptionalCord());
+ msg.clearOptionalCord()
+ .setOptionalCord("hello");
+ assertTrue(msg.hasOptionalCord());
+ msg.clear();
+ assertFalse(msg.hasOptionalCord());
+
+ msg.setOptionalCord("bye");
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertTrue(newMsg.hasOptionalCord());
+ assertEquals("bye", newMsg.getOptionalCord());
+ }
+
+ public void testMicroRepeatedInt32() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedInt32Count());
+ msg.addRepeatedInt32(123);
+ assertEquals(1, msg.getRepeatedInt32Count());
+ assertEquals(123, msg.getRepeatedInt32(0));
+ msg.addRepeatedInt32(456);
+ assertEquals(2, msg.getRepeatedInt32Count());
+ assertEquals(123, msg.getRepeatedInt32(0));
+ assertEquals(456, msg.getRepeatedInt32(1));
+ msg.setRepeatedInt32(0, 789);
+ assertEquals(2, msg.getRepeatedInt32Count());
+ assertEquals(789, msg.getRepeatedInt32(0));
+ assertEquals(456, msg.getRepeatedInt32(1));
+ msg.clearRepeatedInt32();
+ assertEquals(0, msg.getRepeatedInt32Count());
+ msg.clearRepeatedInt32()
+ .addRepeatedInt32(456);
+ assertEquals(1, msg.getRepeatedInt32Count());
+ assertEquals(456, msg.getRepeatedInt32(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedInt32Count());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedInt32(123);
+ assertEquals(1, msg.getRepeatedInt32Count());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedInt32Count());
+ assertEquals(123, newMsg.getRepeatedInt32(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedInt32(123)
+ .addRepeatedInt32(456);
+ assertEquals(2, msg.getRepeatedInt32Count());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 7);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedInt32Count());
+ assertEquals(123, newMsg.getRepeatedInt32(0));
+ assertEquals(456, newMsg.getRepeatedInt32(1));
+ }
+
+ public void testMicroRepeatedInt64() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedInt64Count());
+ msg.addRepeatedInt64(123);
+ assertEquals(1, msg.getRepeatedInt64Count());
+ assertEquals(123, msg.getRepeatedInt64(0));
+ msg.addRepeatedInt64(456);
+ assertEquals(2, msg.getRepeatedInt64Count());
+ assertEquals(123, msg.getRepeatedInt64(0));
+ assertEquals(456, msg.getRepeatedInt64(1));
+ msg.setRepeatedInt64(0, 789);
+ assertEquals(2, msg.getRepeatedInt64Count());
+ assertEquals(789, msg.getRepeatedInt64(0));
+ assertEquals(456, msg.getRepeatedInt64(1));
+ msg.clearRepeatedInt64();
+ assertEquals(0, msg.getRepeatedInt64Count());
+ msg.clearRepeatedInt64()
+ .addRepeatedInt64(456);
+ assertEquals(1, msg.getRepeatedInt64Count());
+ assertEquals(456, msg.getRepeatedInt64(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedInt64Count());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedInt64(123);
+ assertEquals(1, msg.getRepeatedInt64Count());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedInt64Count());
+ assertEquals(123, newMsg.getRepeatedInt64(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedInt64(123)
+ .addRepeatedInt64(456);
+ assertEquals(2, msg.getRepeatedInt64Count());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 7);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedInt64Count());
+ assertEquals(123, newMsg.getRepeatedInt64(0));
+ assertEquals(456, newMsg.getRepeatedInt64(1));
+ }
+
+ public void testMicroRepeatedUint32() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedUint32Count());
+ msg.addRepeatedUint32(123);
+ assertEquals(1, msg.getRepeatedUint32Count());
+ assertEquals(123, msg.getRepeatedUint32(0));
+ msg.addRepeatedUint32(456);
+ assertEquals(2, msg.getRepeatedUint32Count());
+ assertEquals(123, msg.getRepeatedUint32(0));
+ assertEquals(456, msg.getRepeatedUint32(1));
+ msg.setRepeatedUint32(0, 789);
+ assertEquals(2, msg.getRepeatedUint32Count());
+ assertEquals(789, msg.getRepeatedUint32(0));
+ assertEquals(456, msg.getRepeatedUint32(1));
+ msg.clearRepeatedUint32();
+ assertEquals(0, msg.getRepeatedUint32Count());
+ msg.clearRepeatedUint32()
+ .addRepeatedUint32(456);
+ assertEquals(1, msg.getRepeatedUint32Count());
+ assertEquals(456, msg.getRepeatedUint32(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedUint32Count());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedUint32(123);
+ assertEquals(1, msg.getRepeatedUint32Count());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedUint32Count());
+ assertEquals(123, newMsg.getRepeatedUint32(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedUint32(123)
+ .addRepeatedUint32(456);
+ assertEquals(2, msg.getRepeatedUint32Count());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 7);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedUint32Count());
+ assertEquals(123, newMsg.getRepeatedUint32(0));
+ assertEquals(456, newMsg.getRepeatedUint32(1));
+ }
+
+ public void testMicroRepeatedUint64() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedUint64Count());
+ msg.addRepeatedUint64(123);
+ assertEquals(1, msg.getRepeatedUint64Count());
+ assertEquals(123, msg.getRepeatedUint64(0));
+ msg.addRepeatedUint64(456);
+ assertEquals(2, msg.getRepeatedUint64Count());
+ assertEquals(123, msg.getRepeatedUint64(0));
+ assertEquals(456, msg.getRepeatedUint64(1));
+ msg.setRepeatedUint64(0, 789);
+ assertEquals(2, msg.getRepeatedUint64Count());
+ assertEquals(789, msg.getRepeatedUint64(0));
+ assertEquals(456, msg.getRepeatedUint64(1));
+ msg.clearRepeatedUint64();
+ assertEquals(0, msg.getRepeatedUint64Count());
+ msg.clearRepeatedUint64()
+ .addRepeatedUint64(456);
+ assertEquals(1, msg.getRepeatedUint64Count());
+ assertEquals(456, msg.getRepeatedUint64(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedUint64Count());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedUint64(123);
+ assertEquals(1, msg.getRepeatedUint64Count());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedUint64Count());
+ assertEquals(123, newMsg.getRepeatedUint64(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedUint64(123)
+ .addRepeatedUint64(456);
+ assertEquals(2, msg.getRepeatedUint64Count());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 7);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedUint64Count());
+ assertEquals(123, newMsg.getRepeatedUint64(0));
+ assertEquals(456, newMsg.getRepeatedUint64(1));
+ }
+
+ public void testMicroRepeatedSint32() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedSint32Count());
+ msg.addRepeatedSint32(123);
+ assertEquals(1, msg.getRepeatedSint32Count());
+ assertEquals(123, msg.getRepeatedSint32(0));
+ msg.addRepeatedSint32(456);
+ assertEquals(2, msg.getRepeatedSint32Count());
+ assertEquals(123, msg.getRepeatedSint32(0));
+ assertEquals(456, msg.getRepeatedSint32(1));
+ msg.setRepeatedSint32(0, 789);
+ assertEquals(2, msg.getRepeatedSint32Count());
+ assertEquals(789, msg.getRepeatedSint32(0));
+ assertEquals(456, msg.getRepeatedSint32(1));
+ msg.clearRepeatedSint32();
+ assertEquals(0, msg.getRepeatedSint32Count());
+ msg.clearRepeatedSint32()
+ .addRepeatedSint32(456);
+ assertEquals(1, msg.getRepeatedSint32Count());
+ assertEquals(456, msg.getRepeatedSint32(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedSint32Count());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedSint32(123);
+ assertEquals(1, msg.getRepeatedSint32Count());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 4);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedSint32Count());
+ assertEquals(123, newMsg.getRepeatedSint32(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedSint32(123)
+ .addRepeatedSint32(456);
+ assertEquals(2, msg.getRepeatedSint32Count());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 8);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedSint32Count());
+ assertEquals(123, newMsg.getRepeatedSint32(0));
+ assertEquals(456, newMsg.getRepeatedSint32(1));
+ }
+
+ public void testMicroRepeatedSint64() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedSint64Count());
+ msg.addRepeatedSint64(123);
+ assertEquals(1, msg.getRepeatedSint64Count());
+ assertEquals(123, msg.getRepeatedSint64(0));
+ msg.addRepeatedSint64(456);
+ assertEquals(2, msg.getRepeatedSint64Count());
+ assertEquals(123, msg.getRepeatedSint64(0));
+ assertEquals(456, msg.getRepeatedSint64(1));
+ msg.setRepeatedSint64(0, 789);
+ assertEquals(2, msg.getRepeatedSint64Count());
+ assertEquals(789, msg.getRepeatedSint64(0));
+ assertEquals(456, msg.getRepeatedSint64(1));
+ msg.clearRepeatedSint64();
+ assertEquals(0, msg.getRepeatedSint64Count());
+ msg.clearRepeatedSint64()
+ .addRepeatedSint64(456);
+ assertEquals(1, msg.getRepeatedSint64Count());
+ assertEquals(456, msg.getRepeatedSint64(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedSint64Count());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedSint64(123);
+ assertEquals(1, msg.getRepeatedSint64Count());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 4);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedSint64Count());
+ assertEquals(123, newMsg.getRepeatedSint64(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedSint64(123)
+ .addRepeatedSint64(456);
+ assertEquals(2, msg.getRepeatedSint64Count());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 8);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedSint64Count());
+ assertEquals(123, newMsg.getRepeatedSint64(0));
+ assertEquals(456, newMsg.getRepeatedSint64(1));
+ }
+
+ public void testMicroRepeatedFixed32() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedFixed32Count());
+ msg.addRepeatedFixed32(123);
+ assertEquals(1, msg.getRepeatedFixed32Count());
+ assertEquals(123, msg.getRepeatedFixed32(0));
+ msg.addRepeatedFixed32(456);
+ assertEquals(2, msg.getRepeatedFixed32Count());
+ assertEquals(123, msg.getRepeatedFixed32(0));
+ assertEquals(456, msg.getRepeatedFixed32(1));
+ msg.setRepeatedFixed32(0, 789);
+ assertEquals(2, msg.getRepeatedFixed32Count());
+ assertEquals(789, msg.getRepeatedFixed32(0));
+ assertEquals(456, msg.getRepeatedFixed32(1));
+ msg.clearRepeatedFixed32();
+ assertEquals(0, msg.getRepeatedFixed32Count());
+ msg.clearRepeatedFixed32()
+ .addRepeatedFixed32(456);
+ assertEquals(1, msg.getRepeatedFixed32Count());
+ assertEquals(456, msg.getRepeatedFixed32(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedFixed32Count());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedFixed32(123);
+ assertEquals(1, msg.getRepeatedFixed32Count());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedFixed32Count());
+ assertEquals(123, newMsg.getRepeatedFixed32(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedFixed32(123)
+ .addRepeatedFixed32(456);
+ assertEquals(2, msg.getRepeatedFixed32Count());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 12);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedFixed32Count());
+ assertEquals(123, newMsg.getRepeatedFixed32(0));
+ assertEquals(456, newMsg.getRepeatedFixed32(1));
+ }
+
+ public void testMicroRepeatedFixed64() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedFixed64Count());
+ msg.addRepeatedFixed64(123);
+ assertEquals(1, msg.getRepeatedFixed64Count());
+ assertEquals(123, msg.getRepeatedFixed64(0));
+ msg.addRepeatedFixed64(456);
+ assertEquals(2, msg.getRepeatedFixed64Count());
+ assertEquals(123, msg.getRepeatedFixed64(0));
+ assertEquals(456, msg.getRepeatedFixed64(1));
+ msg.setRepeatedFixed64(0, 789);
+ assertEquals(2, msg.getRepeatedFixed64Count());
+ assertEquals(789, msg.getRepeatedFixed64(0));
+ assertEquals(456, msg.getRepeatedFixed64(1));
+ msg.clearRepeatedFixed64();
+ assertEquals(0, msg.getRepeatedFixed64Count());
+ msg.clearRepeatedFixed64()
+ .addRepeatedFixed64(456);
+ assertEquals(1, msg.getRepeatedFixed64Count());
+ assertEquals(456, msg.getRepeatedFixed64(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedFixed64Count());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedFixed64(123);
+ assertEquals(1, msg.getRepeatedFixed64Count());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 10);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedFixed64Count());
+ assertEquals(123, newMsg.getRepeatedFixed64(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedFixed64(123)
+ .addRepeatedFixed64(456);
+ assertEquals(2, msg.getRepeatedFixed64Count());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 20);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedFixed64Count());
+ assertEquals(123, newMsg.getRepeatedFixed64(0));
+ assertEquals(456, newMsg.getRepeatedFixed64(1));
+ }
+
+ public void testMicroRepeatedSfixed32() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedSfixed32Count());
+ msg.addRepeatedSfixed32(123);
+ assertEquals(1, msg.getRepeatedSfixed32Count());
+ assertEquals(123, msg.getRepeatedSfixed32(0));
+ msg.addRepeatedSfixed32(456);
+ assertEquals(2, msg.getRepeatedSfixed32Count());
+ assertEquals(123, msg.getRepeatedSfixed32(0));
+ assertEquals(456, msg.getRepeatedSfixed32(1));
+ msg.setRepeatedSfixed32(0, 789);
+ assertEquals(2, msg.getRepeatedSfixed32Count());
+ assertEquals(789, msg.getRepeatedSfixed32(0));
+ assertEquals(456, msg.getRepeatedSfixed32(1));
+ msg.clearRepeatedSfixed32();
+ assertEquals(0, msg.getRepeatedSfixed32Count());
+ msg.clearRepeatedSfixed32()
+ .addRepeatedSfixed32(456);
+ assertEquals(1, msg.getRepeatedSfixed32Count());
+ assertEquals(456, msg.getRepeatedSfixed32(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedSfixed32Count());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedSfixed32(123);
+ assertEquals(1, msg.getRepeatedSfixed32Count());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedSfixed32Count());
+ assertEquals(123, newMsg.getRepeatedSfixed32(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedSfixed32(123)
+ .addRepeatedSfixed32(456);
+ assertEquals(2, msg.getRepeatedSfixed32Count());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 12);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedSfixed32Count());
+ assertEquals(123, newMsg.getRepeatedSfixed32(0));
+ assertEquals(456, newMsg.getRepeatedSfixed32(1));
+ }
+
+ public void testMicroRepeatedSfixed64() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedSfixed64Count());
+ msg.addRepeatedSfixed64(123);
+ assertEquals(1, msg.getRepeatedSfixed64Count());
+ assertEquals(123, msg.getRepeatedSfixed64(0));
+ msg.addRepeatedSfixed64(456);
+ assertEquals(2, msg.getRepeatedSfixed64Count());
+ assertEquals(123, msg.getRepeatedSfixed64(0));
+ assertEquals(456, msg.getRepeatedSfixed64(1));
+ msg.setRepeatedSfixed64(0, 789);
+ assertEquals(2, msg.getRepeatedSfixed64Count());
+ assertEquals(789, msg.getRepeatedSfixed64(0));
+ assertEquals(456, msg.getRepeatedSfixed64(1));
+ msg.clearRepeatedSfixed64();
+ assertEquals(0, msg.getRepeatedSfixed64Count());
+ msg.clearRepeatedSfixed64()
+ .addRepeatedSfixed64(456);
+ assertEquals(1, msg.getRepeatedSfixed64Count());
+ assertEquals(456, msg.getRepeatedSfixed64(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedSfixed64Count());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedSfixed64(123);
+ assertEquals(1, msg.getRepeatedSfixed64Count());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 10);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedSfixed64Count());
+ assertEquals(123, newMsg.getRepeatedSfixed64(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedSfixed64(123)
+ .addRepeatedSfixed64(456);
+ assertEquals(2, msg.getRepeatedSfixed64Count());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 20);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedSfixed64Count());
+ assertEquals(123, newMsg.getRepeatedSfixed64(0));
+ assertEquals(456, newMsg.getRepeatedSfixed64(1));
+ }
+
+ public void testMicroRepeatedFloat() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedFloatCount());
+ msg.addRepeatedFloat(123f);
+ assertEquals(1, msg.getRepeatedFloatCount());
+ assertTrue(123f == msg.getRepeatedFloat(0));
+ msg.addRepeatedFloat(456f);
+ assertEquals(2, msg.getRepeatedFloatCount());
+ assertTrue(123f == msg.getRepeatedFloat(0));
+ assertTrue(456f == msg.getRepeatedFloat(1));
+ msg.setRepeatedFloat(0, 789f);
+ assertEquals(2, msg.getRepeatedFloatCount());
+ assertTrue(789f == msg.getRepeatedFloat(0));
+ assertTrue(456f == msg.getRepeatedFloat(1));
+ msg.clearRepeatedFloat();
+ assertEquals(0, msg.getRepeatedFloatCount());
+ msg.clearRepeatedFloat()
+ .addRepeatedFloat(456f);
+ assertEquals(1, msg.getRepeatedFloatCount());
+ assertTrue(456f == msg.getRepeatedFloat(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedFloatCount());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedFloat(123f);
+ assertEquals(1, msg.getRepeatedFloatCount());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedFloatCount());
+ assertTrue(123f == newMsg.getRepeatedFloat(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedFloat(123f)
+ .addRepeatedFloat(456f);
+ assertEquals(2, msg.getRepeatedFloatCount());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 12);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedFloatCount());
+ assertTrue(123f == newMsg.getRepeatedFloat(0));
+ assertTrue(456f == newMsg.getRepeatedFloat(1));
+ }
+
+ public void testMicroRepeatedDouble() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedDoubleCount());
+ msg.addRepeatedDouble(123.0);
+ assertEquals(1, msg.getRepeatedDoubleCount());
+ assertTrue(123.0 == msg.getRepeatedDouble(0));
+ msg.addRepeatedDouble(456.0);
+ assertEquals(2, msg.getRepeatedDoubleCount());
+ assertTrue(123.0 == msg.getRepeatedDouble(0));
+ assertTrue(456.0 == msg.getRepeatedDouble(1));
+ msg.setRepeatedDouble(0, 789.0);
+ assertEquals(2, msg.getRepeatedDoubleCount());
+ assertTrue(789.0 == msg.getRepeatedDouble(0));
+ assertTrue(456.0 == msg.getRepeatedDouble(1));
+ msg.clearRepeatedDouble();
+ assertEquals(0, msg.getRepeatedDoubleCount());
+ msg.clearRepeatedDouble()
+ .addRepeatedDouble(456.0);
+ assertEquals(1, msg.getRepeatedDoubleCount());
+ assertTrue(456.0 == msg.getRepeatedDouble(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedDoubleCount());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedDouble(123.0);
+ assertEquals(1, msg.getRepeatedDoubleCount());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 10);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedDoubleCount());
+ assertTrue(123.0 == newMsg.getRepeatedDouble(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedDouble(123.0)
+ .addRepeatedDouble(456.0);
+ assertEquals(2, msg.getRepeatedDoubleCount());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 20);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedDoubleCount());
+ assertTrue(123.0 == newMsg.getRepeatedDouble(0));
+ assertTrue(456.0 == newMsg.getRepeatedDouble(1));
+ }
+
+ public void testMicroRepeatedBool() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedBoolCount());
+ msg.addRepeatedBool(true);
+ assertEquals(1, msg.getRepeatedBoolCount());
+ assertEquals(true, msg.getRepeatedBool(0));
+ msg.addRepeatedBool(false);
+ assertEquals(2, msg.getRepeatedBoolCount());
+ assertEquals(true, msg.getRepeatedBool(0));
+ assertEquals(false, msg.getRepeatedBool(1));
+ msg.setRepeatedBool(0, false);
+ assertEquals(2, msg.getRepeatedBoolCount());
+ assertEquals(false, msg.getRepeatedBool(0));
+ assertEquals(false, msg.getRepeatedBool(1));
+ msg.clearRepeatedBool();
+ assertEquals(0, msg.getRepeatedBoolCount());
+ msg.clearRepeatedBool()
+ .addRepeatedBool(true);
+ assertEquals(1, msg.getRepeatedBoolCount());
+ assertEquals(true, msg.getRepeatedBool(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedBoolCount());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedBool(false);
+ assertEquals(1, msg.getRepeatedBoolCount());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedBoolCount());
+ assertEquals(false, newMsg.getRepeatedBool(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedBool(true)
+ .addRepeatedBool(false);
+ assertEquals(2, msg.getRepeatedBoolCount());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedBoolCount());
+ assertEquals(true, newMsg.getRepeatedBool(0));
+ assertEquals(false, newMsg.getRepeatedBool(1));
+ }
+
+ public void testMicroRepeatedString() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedStringCount());
+ msg.addRepeatedString("hello");
+ assertEquals(1, msg.getRepeatedStringCount());
+ assertEquals("hello", msg.getRepeatedString(0));
+ msg.addRepeatedString("bye");
+ assertEquals(2, msg.getRepeatedStringCount());
+ assertEquals("hello", msg.getRepeatedString(0));
+ assertEquals("bye", msg.getRepeatedString(1));
+ msg.setRepeatedString(0, "boo");
+ assertEquals(2, msg.getRepeatedStringCount());
+ assertEquals("boo", msg.getRepeatedString(0));
+ assertEquals("bye", msg.getRepeatedString(1));
+ msg.clearRepeatedString();
+ assertEquals(0, msg.getRepeatedStringCount());
+ msg.clearRepeatedString()
+ .addRepeatedString("hello");
+ assertEquals(1, msg.getRepeatedStringCount());
+ assertEquals("hello", msg.getRepeatedString(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedStringCount());
+
+ // Test 1 entry and an empty string
+ msg.clear()
+ .addRepeatedString("");
+ assertEquals(1, msg.getRepeatedStringCount());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedStringCount());
+ assertEquals("", newMsg.getRepeatedString(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedString("hello")
+ .addRepeatedString("world");
+ assertEquals(2, msg.getRepeatedStringCount());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 16);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedStringCount());
+ assertEquals("hello", newMsg.getRepeatedString(0));
+ assertEquals("world", newMsg.getRepeatedString(1));
+ }
+
+ public void testMicroRepeatedBytes() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedBytesCount());
+ msg.addRepeatedBytes(ByteStringMicro.copyFromUtf8("hello"));
+ assertEquals(1, msg.getRepeatedBytesCount());
+ assertEquals("hello", msg.getRepeatedBytes(0).toStringUtf8());
+ msg.addRepeatedBytes(ByteStringMicro.copyFromUtf8("bye"));
+ assertEquals(2, msg.getRepeatedBytesCount());
+ assertEquals("hello", msg.getRepeatedBytes(0).toStringUtf8());
+ assertEquals("bye", msg.getRepeatedBytes(1).toStringUtf8());
+ msg.setRepeatedBytes(0, ByteStringMicro.copyFromUtf8("boo"));
+ assertEquals(2, msg.getRepeatedBytesCount());
+ assertEquals("boo", msg.getRepeatedBytes(0).toStringUtf8());
+ assertEquals("bye", msg.getRepeatedBytes(1).toStringUtf8());
+ msg.clearRepeatedBytes();
+ assertEquals(0, msg.getRepeatedBytesCount());
+ msg.clearRepeatedBytes()
+ .addRepeatedBytes(ByteStringMicro.copyFromUtf8("hello"));
+ assertEquals(1, msg.getRepeatedBytesCount());
+ assertEquals("hello", msg.getRepeatedBytes(0).toStringUtf8());
+ msg.clear();
+ assertEquals(0, msg.getRepeatedBytesCount());
+
+ // Test 1 entry and an empty byte array can be serialized
+ msg.clear()
+ .addRepeatedBytes(ByteStringMicro.copyFromUtf8(""));
+ assertEquals(1, msg.getRepeatedBytesCount());
+ assertEquals("", msg.getRepeatedBytes(0).toStringUtf8());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedBytesCount());
+ assertEquals("", newMsg.getRepeatedBytes(0).toStringUtf8());
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedBytes(ByteStringMicro.copyFromUtf8("hello"))
+ .addRepeatedBytes(ByteStringMicro.copyFromUtf8("world"));
+ assertEquals(2, msg.getRepeatedBytesCount());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 16);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedBytesCount());
+ assertEquals("hello", newMsg.getRepeatedBytes(0).toStringUtf8());
+ assertEquals("world", newMsg.getRepeatedBytes(1).toStringUtf8());
+ }
+
+ public void testMicroRepeatedGroup() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ TestAllTypesMicro.RepeatedGroup group0 =
+ new TestAllTypesMicro.RepeatedGroup().setA(0);
+ TestAllTypesMicro.RepeatedGroup group1 =
+ new TestAllTypesMicro.RepeatedGroup().setA(1);
+ TestAllTypesMicro.RepeatedGroup group2 =
+ new TestAllTypesMicro.RepeatedGroup().setA(2);
+
+ msg.addRepeatedGroup(group0);
+ assertEquals(1, msg.getRepeatedGroupCount());
+ assertEquals(0, msg.getRepeatedGroup(0).getA());
+ msg.addRepeatedGroup(group1);
+ assertEquals(2, msg.getRepeatedGroupCount());
+ assertEquals(0, msg.getRepeatedGroup(0).getA());
+ assertEquals(1, msg.getRepeatedGroup(1).getA());
+ msg.setRepeatedGroup(0, group2);
+ assertEquals(2, msg.getRepeatedGroupCount());
+ assertEquals(2, msg.getRepeatedGroup(0).getA());
+ assertEquals(1, msg.getRepeatedGroup(1).getA());
+ msg.clearRepeatedGroup();
+ assertEquals(0, msg.getRepeatedGroupCount());
+ msg.clearRepeatedGroup()
+ .addRepeatedGroup(group1);
+ assertEquals(1, msg.getRepeatedGroupCount());
+ assertEquals(1, msg.getRepeatedGroup(0).getA());
+ msg.clear();
+ assertEquals(0, msg.getRepeatedGroupCount());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedGroup(group0);
+ assertEquals(1, msg.getRepeatedGroupCount());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 7);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedGroupCount());
+ assertEquals(0, newMsg.getRepeatedGroup(0).getA());
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedGroup(group0)
+ .addRepeatedGroup(group1);
+ assertEquals(2, msg.getRepeatedGroupCount());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 14);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedGroupCount());
+ assertEquals(0, newMsg.getRepeatedGroup(0).getA());
+ assertEquals(1, newMsg.getRepeatedGroup(1).getA());
+ }
+
+
+ public void testMicroRepeatedNestedMessage() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ TestAllTypesMicro.NestedMessage nestedMsg0 =
+ new TestAllTypesMicro.NestedMessage().setBb(0);
+ TestAllTypesMicro.NestedMessage nestedMsg1 =
+ new TestAllTypesMicro.NestedMessage().setBb(1);
+ TestAllTypesMicro.NestedMessage nestedMsg2 =
+ new TestAllTypesMicro.NestedMessage().setBb(2);
+
+ msg.addRepeatedNestedMessage(nestedMsg0);
+ assertEquals(1, msg.getRepeatedNestedMessageCount());
+ assertEquals(0, msg.getRepeatedNestedMessage(0).getBb());
+ msg.addRepeatedNestedMessage(nestedMsg1);
+ assertEquals(2, msg.getRepeatedNestedMessageCount());
+ assertEquals(0, msg.getRepeatedNestedMessage(0).getBb());
+ assertEquals(1, msg.getRepeatedNestedMessage(1).getBb());
+ msg.setRepeatedNestedMessage(0, nestedMsg2);
+ assertEquals(2, msg.getRepeatedNestedMessageCount());
+ assertEquals(2, msg.getRepeatedNestedMessage(0).getBb());
+ assertEquals(1, msg.getRepeatedNestedMessage(1).getBb());
+ msg.clearRepeatedNestedMessage();
+ assertEquals(0, msg.getRepeatedNestedMessageCount());
+ msg.clearRepeatedNestedMessage()
+ .addRepeatedNestedMessage(nestedMsg1);
+ assertEquals(1, msg.getRepeatedNestedMessageCount());
+ assertEquals(1, msg.getRepeatedNestedMessage(0).getBb());
+ msg.clear();
+ assertEquals(0, msg.getRepeatedNestedMessageCount());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedNestedMessage(nestedMsg0);
+ assertEquals(1, msg.getRepeatedNestedMessageCount());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedNestedMessageCount());
+ assertEquals(0, newMsg.getRepeatedNestedMessage(0).getBb());
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedNestedMessage(nestedMsg0)
+ .addRepeatedNestedMessage(nestedMsg1);
+ assertEquals(2, msg.getRepeatedNestedMessageCount());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 10);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedNestedMessageCount());
+ assertEquals(0, newMsg.getRepeatedNestedMessage(0).getBb());
+ assertEquals(1, newMsg.getRepeatedNestedMessage(1).getBb());
+ }
+
+ public void testMicroRepeatedForeignMessage() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ MicroOuterClass.ForeignMessageMicro foreignMsg0 =
+ new MicroOuterClass.ForeignMessageMicro().setC(0);
+ MicroOuterClass.ForeignMessageMicro foreignMsg1 =
+ new MicroOuterClass.ForeignMessageMicro().setC(1);
+ MicroOuterClass.ForeignMessageMicro foreignMsg2 =
+ new MicroOuterClass.ForeignMessageMicro().setC(2);
+
+ msg.addRepeatedForeignMessage(foreignMsg0);
+ assertEquals(1, msg.getRepeatedForeignMessageCount());
+ assertEquals(0, msg.getRepeatedForeignMessage(0).getC());
+ msg.addRepeatedForeignMessage(foreignMsg1);
+ assertEquals(2, msg.getRepeatedForeignMessageCount());
+ assertEquals(0, msg.getRepeatedForeignMessage(0).getC());
+ assertEquals(1, msg.getRepeatedForeignMessage(1).getC());
+ msg.setRepeatedForeignMessage(0, foreignMsg2);
+ assertEquals(2, msg.getRepeatedForeignMessageCount());
+ assertEquals(2, msg.getRepeatedForeignMessage(0).getC());
+ assertEquals(1, msg.getRepeatedForeignMessage(1).getC());
+ msg.clearRepeatedForeignMessage();
+ assertEquals(0, msg.getRepeatedForeignMessageCount());
+ msg.clearRepeatedForeignMessage()
+ .addRepeatedForeignMessage(foreignMsg1);
+ assertEquals(1, msg.getRepeatedForeignMessageCount());
+ assertEquals(1, msg.getRepeatedForeignMessage(0).getC());
+ msg.clear();
+ assertEquals(0, msg.getRepeatedForeignMessageCount());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedForeignMessage(foreignMsg0);
+ assertEquals(1, msg.getRepeatedForeignMessageCount());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedForeignMessageCount());
+ assertEquals(0, newMsg.getRepeatedForeignMessage(0).getC());
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedForeignMessage(foreignMsg0)
+ .addRepeatedForeignMessage(foreignMsg1);
+ assertEquals(2, msg.getRepeatedForeignMessageCount());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 10);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedForeignMessageCount());
+ assertEquals(0, newMsg.getRepeatedForeignMessage(0).getC());
+ assertEquals(1, newMsg.getRepeatedForeignMessage(1).getC());
+ }
+
+ public void testMicroRepeatedImportMessage() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ UnittestImportMicro.ImportMessageMicro importMsg0 =
+ new UnittestImportMicro.ImportMessageMicro().setD(0);
+ UnittestImportMicro.ImportMessageMicro importMsg1 =
+ new UnittestImportMicro.ImportMessageMicro().setD(1);
+ UnittestImportMicro.ImportMessageMicro importMsg2 =
+ new UnittestImportMicro.ImportMessageMicro().setD(2);
+
+ msg.addRepeatedImportMessage(importMsg0);
+ assertEquals(1, msg.getRepeatedImportMessageCount());
+ assertEquals(0, msg.getRepeatedImportMessage(0).getD());
+ msg.addRepeatedImportMessage(importMsg1);
+ assertEquals(2, msg.getRepeatedImportMessageCount());
+ assertEquals(0, msg.getRepeatedImportMessage(0).getD());
+ assertEquals(1, msg.getRepeatedImportMessage(1).getD());
+ msg.setRepeatedImportMessage(0, importMsg2);
+ assertEquals(2, msg.getRepeatedImportMessageCount());
+ assertEquals(2, msg.getRepeatedImportMessage(0).getD());
+ assertEquals(1, msg.getRepeatedImportMessage(1).getD());
+ msg.clearRepeatedImportMessage();
+ assertEquals(0, msg.getRepeatedImportMessageCount());
+ msg.clearRepeatedImportMessage()
+ .addRepeatedImportMessage(importMsg1);
+ assertEquals(1, msg.getRepeatedImportMessageCount());
+ assertEquals(1, msg.getRepeatedImportMessage(0).getD());
+ msg.clear();
+ assertEquals(0, msg.getRepeatedImportMessageCount());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedImportMessage(importMsg0);
+ assertEquals(1, msg.getRepeatedImportMessageCount());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 5);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedImportMessageCount());
+ assertEquals(0, newMsg.getRepeatedImportMessage(0).getD());
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedImportMessage(importMsg0)
+ .addRepeatedImportMessage(importMsg1);
+ assertEquals(2, msg.getRepeatedImportMessageCount());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 10);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedImportMessageCount());
+ assertEquals(0, newMsg.getRepeatedImportMessage(0).getD());
+ assertEquals(1, newMsg.getRepeatedImportMessage(1).getD());
+ }
+
+ public void testMicroRepeatedNestedEnum() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ msg.addRepeatedNestedEnum(TestAllTypesMicro.FOO);
+ assertEquals(1, msg.getRepeatedNestedEnumCount());
+ assertEquals(TestAllTypesMicro.FOO, msg.getRepeatedNestedEnum(0));
+ msg.addRepeatedNestedEnum(TestAllTypesMicro.BAR);
+ assertEquals(2, msg.getRepeatedNestedEnumCount());
+ assertEquals(TestAllTypesMicro.FOO, msg.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypesMicro.BAR, msg.getRepeatedNestedEnum(1));
+ msg.setRepeatedNestedEnum(0, TestAllTypesMicro.BAZ);
+ assertEquals(2, msg.getRepeatedNestedEnumCount());
+ assertEquals(TestAllTypesMicro.BAZ, msg.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypesMicro.BAR, msg.getRepeatedNestedEnum(1));
+ msg.clearRepeatedNestedEnum();
+ assertEquals(0, msg.getRepeatedNestedEnumCount());
+ msg.clearRepeatedNestedEnum()
+ .addRepeatedNestedEnum(TestAllTypesMicro.BAR);
+ assertEquals(1, msg.getRepeatedNestedEnumCount());
+ assertEquals(TestAllTypesMicro.BAR, msg.getRepeatedNestedEnum(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedNestedEnumCount());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedNestedEnum(TestAllTypesMicro.FOO);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedNestedEnumCount());
+ assertEquals(TestAllTypesMicro.FOO, msg.getRepeatedNestedEnum(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedNestedEnum(TestAllTypesMicro.FOO)
+ .addRepeatedNestedEnum(TestAllTypesMicro.BAR);
+ assertEquals(2, msg.getRepeatedNestedEnumCount());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedNestedEnumCount());
+ assertEquals(TestAllTypesMicro.FOO, msg.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypesMicro.BAR, msg.getRepeatedNestedEnum(1));
+ }
+
+ public void testMicroRepeatedForeignEnum() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ msg.addRepeatedForeignEnum(MicroOuterClass.FOREIGN_MICRO_FOO);
+ assertEquals(1, msg.getRepeatedForeignEnumCount());
+ assertEquals(MicroOuterClass.FOREIGN_MICRO_FOO, msg.getRepeatedForeignEnum(0));
+ msg.addRepeatedForeignEnum(MicroOuterClass.FOREIGN_MICRO_BAR);
+ assertEquals(2, msg.getRepeatedForeignEnumCount());
+ assertEquals(MicroOuterClass.FOREIGN_MICRO_FOO, msg.getRepeatedForeignEnum(0));
+ assertEquals(MicroOuterClass.FOREIGN_MICRO_BAR, msg.getRepeatedForeignEnum(1));
+ msg.setRepeatedForeignEnum(0, MicroOuterClass.FOREIGN_MICRO_BAZ);
+ assertEquals(2, msg.getRepeatedForeignEnumCount());
+ assertEquals(MicroOuterClass.FOREIGN_MICRO_BAZ, msg.getRepeatedForeignEnum(0));
+ assertEquals(MicroOuterClass.FOREIGN_MICRO_BAR, msg.getRepeatedForeignEnum(1));
+ msg.clearRepeatedForeignEnum();
+ assertEquals(0, msg.getRepeatedForeignEnumCount());
+ msg.clearRepeatedForeignEnum()
+ .addRepeatedForeignEnum(MicroOuterClass.FOREIGN_MICRO_BAR);
+ assertEquals(1, msg.getRepeatedForeignEnumCount());
+ assertEquals(MicroOuterClass.FOREIGN_MICRO_BAR, msg.getRepeatedForeignEnum(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedForeignEnumCount());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedForeignEnum(MicroOuterClass.FOREIGN_MICRO_FOO);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedForeignEnumCount());
+ assertEquals(MicroOuterClass.FOREIGN_MICRO_FOO, msg.getRepeatedForeignEnum(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedForeignEnum(MicroOuterClass.FOREIGN_MICRO_FOO)
+ .addRepeatedForeignEnum(MicroOuterClass.FOREIGN_MICRO_BAR);
+ assertEquals(2, msg.getRepeatedForeignEnumCount());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedForeignEnumCount());
+ assertEquals(MicroOuterClass.FOREIGN_MICRO_FOO, msg.getRepeatedForeignEnum(0));
+ assertEquals(MicroOuterClass.FOREIGN_MICRO_BAR, msg.getRepeatedForeignEnum(1));
+ }
+
+ public void testMicroRepeatedImportEnum() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ msg.addRepeatedImportEnum(UnittestImportMicro.IMPORT_MICRO_FOO);
+ assertEquals(1, msg.getRepeatedImportEnumCount());
+ assertEquals(UnittestImportMicro.IMPORT_MICRO_FOO, msg.getRepeatedImportEnum(0));
+ msg.addRepeatedImportEnum(UnittestImportMicro.IMPORT_MICRO_BAR);
+ assertEquals(2, msg.getRepeatedImportEnumCount());
+ assertEquals(UnittestImportMicro.IMPORT_MICRO_FOO, msg.getRepeatedImportEnum(0));
+ assertEquals(UnittestImportMicro.IMPORT_MICRO_BAR, msg.getRepeatedImportEnum(1));
+ msg.setRepeatedImportEnum(0, UnittestImportMicro.IMPORT_MICRO_BAZ);
+ assertEquals(2, msg.getRepeatedImportEnumCount());
+ assertEquals(UnittestImportMicro.IMPORT_MICRO_BAZ, msg.getRepeatedImportEnum(0));
+ assertEquals(UnittestImportMicro.IMPORT_MICRO_BAR, msg.getRepeatedImportEnum(1));
+ msg.clearRepeatedImportEnum();
+ assertEquals(0, msg.getRepeatedImportEnumCount());
+ msg.clearRepeatedImportEnum()
+ .addRepeatedImportEnum(UnittestImportMicro.IMPORT_MICRO_BAR);
+ assertEquals(1, msg.getRepeatedImportEnumCount());
+ assertEquals(UnittestImportMicro.IMPORT_MICRO_BAR, msg.getRepeatedImportEnum(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedImportEnumCount());
+
+ // Test 1 entry
+ msg.clear()
+ .addRepeatedImportEnum(UnittestImportMicro.IMPORT_MICRO_FOO);
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedImportEnumCount());
+ assertEquals(UnittestImportMicro.IMPORT_MICRO_FOO, msg.getRepeatedImportEnum(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedImportEnum(UnittestImportMicro.IMPORT_MICRO_FOO)
+ .addRepeatedImportEnum(UnittestImportMicro.IMPORT_MICRO_BAR);
+ assertEquals(2, msg.getRepeatedImportEnumCount());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 6);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedImportEnumCount());
+ assertEquals(UnittestImportMicro.IMPORT_MICRO_FOO, msg.getRepeatedImportEnum(0));
+ assertEquals(UnittestImportMicro.IMPORT_MICRO_BAR, msg.getRepeatedImportEnum(1));
+ }
+
+ public void testMicroRepeatedStringPiece() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedStringPieceCount());
+ msg.addRepeatedStringPiece("hello");
+ assertEquals(1, msg.getRepeatedStringPieceCount());
+ assertEquals("hello", msg.getRepeatedStringPiece(0));
+ msg.addRepeatedStringPiece("bye");
+ assertEquals(2, msg.getRepeatedStringPieceCount());
+ assertEquals("hello", msg.getRepeatedStringPiece(0));
+ assertEquals("bye", msg.getRepeatedStringPiece(1));
+ msg.setRepeatedStringPiece(0, "boo");
+ assertEquals(2, msg.getRepeatedStringPieceCount());
+ assertEquals("boo", msg.getRepeatedStringPiece(0));
+ assertEquals("bye", msg.getRepeatedStringPiece(1));
+ msg.clearRepeatedStringPiece();
+ assertEquals(0, msg.getRepeatedStringPieceCount());
+ msg.clearRepeatedStringPiece()
+ .addRepeatedStringPiece("hello");
+ assertEquals(1, msg.getRepeatedStringPieceCount());
+ assertEquals("hello", msg.getRepeatedStringPiece(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedStringPieceCount());
+
+ // Test 1 entry and an empty string
+ msg.clear()
+ .addRepeatedStringPiece("");
+ assertEquals(1, msg.getRepeatedStringPieceCount());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedStringPieceCount());
+ assertEquals("", newMsg.getRepeatedStringPiece(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedStringPiece("hello")
+ .addRepeatedStringPiece("world");
+ assertEquals(2, msg.getRepeatedStringPieceCount());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 16);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedStringPieceCount());
+ assertEquals("hello", newMsg.getRepeatedStringPiece(0));
+ assertEquals("world", newMsg.getRepeatedStringPiece(1));
+ }
+
+ public void testMicroRepeatedCord() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertEquals(0, msg.getRepeatedCordCount());
+ msg.addRepeatedCord("hello");
+ assertEquals(1, msg.getRepeatedCordCount());
+ assertEquals("hello", msg.getRepeatedCord(0));
+ msg.addRepeatedCord("bye");
+ assertEquals(2, msg.getRepeatedCordCount());
+ assertEquals("hello", msg.getRepeatedCord(0));
+ assertEquals("bye", msg.getRepeatedCord(1));
+ msg.setRepeatedCord(0, "boo");
+ assertEquals(2, msg.getRepeatedCordCount());
+ assertEquals("boo", msg.getRepeatedCord(0));
+ assertEquals("bye", msg.getRepeatedCord(1));
+ msg.clearRepeatedCord();
+ assertEquals(0, msg.getRepeatedCordCount());
+ msg.clearRepeatedCord()
+ .addRepeatedCord("hello");
+ assertEquals(1, msg.getRepeatedCordCount());
+ assertEquals("hello", msg.getRepeatedCord(0));
+ msg.clear();
+ assertEquals(0, msg.getRepeatedCordCount());
+
+ // Test 1 entry and an empty string
+ msg.clear()
+ .addRepeatedCord("");
+ assertEquals(1, msg.getRepeatedCordCount());
+ byte [] result = msg.toByteArray();
+ int msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 3);
+ assertEquals(result.length, msgSerializedSize);
+ TestAllTypesMicro newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(1, newMsg.getRepeatedCordCount());
+ assertEquals("", newMsg.getRepeatedCord(0));
+
+ // Test 2 entries
+ msg.clear()
+ .addRepeatedCord("hello")
+ .addRepeatedCord("world");
+ assertEquals(2, msg.getRepeatedCordCount());
+ result = msg.toByteArray();
+ msgSerializedSize = msg.getSerializedSize();
+ //System.out.printf("mss=%d result.length=%d\n", msgSerializedSize, result.length);
+ assertTrue(msgSerializedSize == 16);
+ assertEquals(result.length, msgSerializedSize);
+
+ newMsg = TestAllTypesMicro.parseFrom(result);
+ assertEquals(2, newMsg.getRepeatedCordCount());
+ assertEquals("hello", newMsg.getRepeatedCord(0));
+ assertEquals("world", newMsg.getRepeatedCord(1));
+ }
+
+ public void testMicroDefaults() throws Exception {
+ TestAllTypesMicro msg = new TestAllTypesMicro();
+ assertFalse(msg.hasDefaultInt32());
+ assertEquals(41, msg.getDefaultInt32());
+ assertFalse(msg.hasDefaultInt64());
+ assertEquals(42, msg.getDefaultInt64());
+ assertFalse(msg.hasDefaultUint32());
+ assertEquals(43, msg.getDefaultUint32());
+ assertFalse(msg.hasDefaultUint64());
+ assertEquals(44, msg.getDefaultUint64());
+ assertFalse(msg.hasDefaultSint32());
+ assertEquals(-45, msg.getDefaultSint32());
+ assertFalse(msg.hasDefaultSint64());
+ assertEquals(46, msg.getDefaultSint64());
+ assertFalse(msg.hasDefaultFixed32());
+ assertEquals(47, msg.getDefaultFixed32());
+ assertFalse(msg.hasDefaultFixed64());
+ assertEquals(48, msg.getDefaultFixed64());
+ assertFalse(msg.hasDefaultSfixed32());
+ assertEquals(49, msg.getDefaultSfixed32());
+ assertFalse(msg.hasDefaultSfixed64());
+ assertEquals(-50, msg.getDefaultSfixed64());
+ assertFalse(msg.hasDefaultFloat());
+ assertTrue(51.5f == msg.getDefaultFloat());
+ assertFalse(msg.hasDefaultDouble());
+ assertTrue(52.0e3 == msg.getDefaultDouble());
+ assertFalse(msg.hasDefaultBool());
+ assertEquals(true, msg.getDefaultBool());
+ assertFalse(msg.hasDefaultString());
+ assertEquals("hello", msg.getDefaultString());
+ assertFalse(msg.hasDefaultBytes());
+ assertEquals("world", msg.getDefaultBytes().toStringUtf8());
+ assertFalse(msg.hasDefaultNestedEnum());
+ assertEquals(TestAllTypesMicro.BAR, msg.getDefaultNestedEnum());
+ assertFalse(msg.hasDefaultForeignEnum());
+ assertEquals(MicroOuterClass.FOREIGN_MICRO_BAR, msg.getDefaultForeignEnum());
+ assertFalse(msg.hasDefaultImportEnum());
+ assertEquals(UnittestImportMicro.IMPORT_MICRO_BAR, msg.getDefaultImportEnum());
+ }
+}
diff --git a/java/src/test/java/com/google/protobuf/PerfTimer.java b/java/src/test/java/com/google/protobuf/PerfTimer.java
new file mode 100644
index 0000000..d6df4ff
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/PerfTimer.java
@@ -0,0 +1,832 @@
+/*
+ * Copyright (C) 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.protobuf;
+
+import java.util.Arrays;
+
+/**
+ * A Performance Timing class that can be used to estimate the amount of time a
+ * sequence of code takes. The typical code sequence would be as follows:</p>
+ * <code>
+ PerfTimer pt = new PerfTimer();
+ pt.calibrate();
+ pt.timeEachAutomatically(new Runnable() = {
+ public void run() {
+ // Add code to time
+ }
+ });
+ System.out.printf("time per loop=" + pt);
+
+ * The calibrate method determines the overhead of timing the run() method and
+ * the number of times to call the run() method to have approximately 1% precision
+ * for timing. The method pt.stats() method will return a string containing some
+ * statistics tpl, il, ol, min, max, mean, median, stddev and total.
+ *
+ * tpl ::= Timer per loop
+ * min ::= minimum time one call to run() took
+ * stddev ::= Standard deviation of the collected times
+ * mean ::= the average time to call run()
+ * median ::= 1/2 the times were > than this time and 1/2 were less.
+ * total ::= Sum of the times collected.
+ * il ::= innerLoops; the number of times run() between each call to start/stop
+ * ol ::= outerLoops, the number of times start/stop was called
+ *
+ * You can also use start/stop/restart to do simple timing:
+ *
+ * pt.start();
+ * a += 1;
+ * pt.stop();
+ * pt.log("time=" + pt);
+ * pt.restart();
+ * doSomething();
+ * pt.stop();
+ * System.out.printf("time=" + pt);
+ * </code>
+ *
+ * @author wink@google.com (Wink Saville)
+ */
+public class PerfTimer {
+ /** No debug */
+ public static final int DEBUG_LEVEL_NONE = 0;
+
+ /** Some debug */
+ public static final int DEBUG_LEVEL_SOME = 1;
+
+ /** All debug */
+ public static final int DEBUG_LEVEL_ALL = 2;
+
+ /** Timer ticks per microsecond */
+ private static final double TICKS_PER_MICROSECOND = 1000.0;
+
+ /** Random number generator */
+ java.util.Random rng = new java.util.Random();
+
+ /** get ticks */
+ private static long getTicks() {
+ return System.nanoTime();
+ }
+
+ /** Debug logging */
+ private static void log(String s) {
+ System.out.printf(String.format("[PerfTimer] %s\n", s));
+ }
+
+ /** Outer loops for timeEachAutomatically */
+ private static final int OUTER_LOOPS = 100;
+
+ /** Thrown if an error occurs while timing */
+ public static class PerfTimerException extends RuntimeException {
+ }
+
+ /**
+ * Calibration record
+ */
+ public static class CalibrationRec {
+ /** Runnable overhead */
+ public double mRunnableOverheadInMicros = 0.0;
+
+ /** Minimum Threshold value for timeEachAutomaticaly */
+ public double mMinThresholdInMicros = 3000.0;
+
+ /** Maximum Threshold value for timeEachAutomaticaly */
+ public double mMaxThresholdInMicros = 6000.0;
+
+ /** Desired precision in decimal digits */
+ public double mPrecisionInDecimalDigits = 2.0;
+
+ /**
+ * Default number of retries if the standard deviation ratio is too
+ * large
+ */
+ public final int mStdDevRetrys = 5;
+
+ /** Default maximum standard deviation radio */
+ public final double mMaxStdDevRatio = 0.15;
+
+ /** Number of votes looking for smallest time per loop */
+ public final int mVotes = 3;
+
+ /** Convert to string */
+ @Override
+ public String toString() {
+ return String
+ .format(
+ "oh=%.6fus minT=%.6fus maxT=%.6fus prc=%,.3f stdDevRetrys=%d maxStdDevRatio=%.2f votes=%d",
+ mRunnableOverheadInMicros, mMinThresholdInMicros,
+ mMaxThresholdInMicros, mPrecisionInDecimalDigits, mStdDevRetrys,
+ mMaxStdDevRatio, mVotes);
+ }
+ }
+
+ /**
+ * Calibration record
+ */
+ private CalibrationRec mCr;
+
+ /**
+ * Statistics calculated on the timing data.
+ */
+ public static class Stats {
+ /** Number of outer loops */
+ private int mOuterLoops;
+
+ /** Number of inner loops */
+ private int mInnerLoops;
+
+ /** Minimum time in times array */
+ private long mMin;
+
+ /** Maximum time in times array */
+ private long mMax;
+
+ /** Median value in times array */
+ private double mMedian;
+
+ /** The mean (average) of the values in times array */
+ private double mMean;
+
+ /** The standard deviation of the values in times array */
+ private double mStdDev;
+
+ private int mStdDevTooLargeCount;
+
+ /** Sum of the times in the times array */
+ private double mTotal;
+
+ /** Initialize */
+ public void init() {
+ mInnerLoops = 1;
+ mOuterLoops = 1;
+ mMin = 0;
+ mMax = 0;
+ mMedian = 0;
+ mMean = 0;
+ mStdDev = 0;
+ mStdDevTooLargeCount = 0;
+ mTotal = 0;
+ }
+
+ /** Constructor */
+ public Stats() {
+ init();
+ }
+
+ /** Set number of inner loops */
+ public void setInnerLoops(int loops) {
+ mInnerLoops = loops;
+ }
+
+ /** Get number of inner loops */
+ public int getInnerLoops() {
+ return mInnerLoops;
+ }
+
+ /** Set number of inner loops */
+ public void setOuterLoops(int loops) {
+ mOuterLoops = loops;
+ }
+
+ /** Get number of inner loops */
+ public int getOuterLoops() {
+ return mOuterLoops;
+ }
+
+ /**
+ * Minimum value of collected data in microseconds, valid after analyze.
+ */
+ public double getMinInMicros() {
+ return mMin / TICKS_PER_MICROSECOND;
+ }
+
+ /**
+ * Maximum value of collected data in microseconds, valid after analyze.
+ */
+ public double getMaxInMicros() {
+ return mMax / TICKS_PER_MICROSECOND;
+ }
+
+ /**
+ * Sum of the values of collected data in microseconds, valid after
+ * analyze.
+ */
+ public double getTotalInMicros() {
+ return mTotal / TICKS_PER_MICROSECOND;
+ }
+
+ /** Sum of the values of collected data in seconds, valid after analyze. */
+ public double getTotalInSecs() {
+ return mTotal / (TICKS_PER_MICROSECOND * 1000000.0);
+ }
+
+ /** Sum of the values of collected data in seconds, valid after analyze. */
+ public double getMeanInMicros() {
+ return mMean / TICKS_PER_MICROSECOND;
+ }
+
+ /** Median value of collected data in microseconds, valid after analyze. */
+ public double getMedianInMicros() {
+ return mMedian / TICKS_PER_MICROSECOND;
+ }
+
+ /**
+ * Standard deviation of collected data in microseconds, valid after
+ * analyze.
+ */
+ public double getStdDevInMicros() {
+ return mStdDev / TICKS_PER_MICROSECOND;
+ }
+
+ public double getStdDevRatio() {
+ return mStdDev / mMin;
+ }
+
+ /** Return true if (mStdDev / mMin) <= maxStdDevRation */
+ public boolean stdDevOk(double maxStdDevRatio) {
+ return getStdDevRatio() <= maxStdDevRatio;
+ }
+
+ /** Increment StdDevTooLargeCount */
+ public void incStdDevTooLargeCount() {
+ mStdDevTooLargeCount += 1;
+ }
+
+ /** Return number of times stdDev was not ok */
+ public int getStdDevTooLargeCount() {
+ return mStdDevTooLargeCount;
+ }
+
+ /** Return time per loop */
+ public double getTimePerLoop() {
+ return mMin / TICKS_PER_MICROSECOND / mInnerLoops;
+ }
+
+ /**
+ * Calculate the stats for the data. Note the data in the range will be
+ * sorted.
+ *
+ * @param data
+ * @param count
+ */
+ public Stats calculate(long data[], int count) {
+ if (count == 1) {
+ mMin = mMax = data[0];
+ mTotal = mMedian = mMean = data[0];
+ mStdDev = 0;
+ } else if (count > 1) {
+ Arrays.sort(data, 0, count);
+ mMin = data[0];
+ mMax = data[count - 1];
+ if ((count & 1) == 1) {
+ mMedian = data[((count + 1) / 2) - 1];
+ } else {
+ mMedian = (data[count / 2] + data[(count / 2) - 1]) / 2;
+ }
+ mTotal = 0;
+ double sumSquares = 0;
+ for (int i = 0; i < count; i++) {
+ long t = data[i];
+ mTotal += t;
+ sumSquares += t * t;
+ }
+ mMean = mTotal / count;
+ double variance = (sumSquares / count) - (mMean * mMean);
+ mStdDev = Math.pow(variance, 0.5);
+ } else {
+ init();
+ }
+ return this;
+ }
+
+ /** Convert to string */
+ @Override
+ public String toString() {
+ double timePerLoop = getTimePerLoop();
+ double stdDevPerLoop = mStdDev / TICKS_PER_MICROSECOND / mInnerLoops;
+ return String.format(
+ "tpl=%,.6fus stdDev=%,.6fus tpl/stdDev=%.2fpercent min=%,.6fus median=%,.6fus mean=%,.6fus max=%,.6fus total=%,.6fs il=%d, ol=%d tlc=%d",
+ timePerLoop, stdDevPerLoop, (stdDevPerLoop / timePerLoop) * 100, mMin
+ / TICKS_PER_MICROSECOND, mMedian / TICKS_PER_MICROSECOND, mMean
+ / TICKS_PER_MICROSECOND, mMax / TICKS_PER_MICROSECOND, mTotal
+ / (TICKS_PER_MICROSECOND * 1000000.0), mInnerLoops, mOuterLoops, mStdDevTooLargeCount);
+ }
+ }
+
+ /** Statistics */
+ private Stats mStats = new Stats();
+
+ /** Statistics of the clock precision */
+ private Stats mClockStats;
+
+ /** Number of items in times array */
+ private int mCount;
+
+ /** Array of stop - start times */
+ private long mTimes[];
+
+ /** Time of last started */
+ private long mStart;
+
+ /** Sleep a little so we don't look like a hog */
+ private void sleep() {
+ try {
+ Thread.sleep(0);
+ } catch (InterruptedException e) {
+ // Ignore exception
+ }
+ }
+
+ /** Empty Runnable used for determining overhead */
+ private Runnable mEmptyRunnable = new Runnable() {
+ public void run() {
+ }
+ };
+
+ /** Initialize */
+ private void init(int maxCount, CalibrationRec cr) {
+ mTimes = new long[maxCount];
+ mCr = cr;
+ reset();
+ }
+
+ /** Construct the stop watch */
+ public PerfTimer() {
+ init(10, new CalibrationRec());
+ }
+
+ /** Construct setting size of times array */
+ public PerfTimer(int maxCount) {
+ init(maxCount, new CalibrationRec());
+ }
+
+ /** Construct the stop watch */
+ public PerfTimer(CalibrationRec cr) {
+ init(10, cr);
+ }
+
+ /** Construct the stop watch */
+ public PerfTimer(int maxCount, CalibrationRec cr) {
+ init(maxCount, cr);
+ }
+
+ /** Reset the contents of the times array */
+ public PerfTimer reset() {
+ mCount = 0;
+ mStats.init();
+ return this;
+ }
+
+ /** Reset and then start the timer */
+ public PerfTimer restart() {
+ reset();
+ mStart = getTicks();
+ return this;
+ }
+
+ /** Start timing */
+ public PerfTimer start() {
+ mStart = getTicks();
+ return this;
+ }
+
+ /**
+ * Record the difference between start and now in the times array
+ * incrementing count. The time will be stored in the times array if the
+ * array is not full.
+ */
+ public PerfTimer stop() {
+ long stop = getTicks();
+ if (mCount < mTimes.length) {
+ mTimes[mCount++] = stop - mStart;
+ }
+ return this;
+ }
+
+ /**
+ * Time how long it takes to execute runnable.run() innerLoop number of
+ * times outerLoops number of times.
+ *
+ * @param outerLoops
+ * @param innerLoops
+ * @param runnable
+ * @return PerfTimer
+ */
+ public PerfTimer timeEach(Stats stats, int outerLoops, int innerLoops, Runnable runnable) {
+ reset();
+ resize(outerLoops);
+ stats.setOuterLoops(outerLoops);
+ stats.setInnerLoops(innerLoops);
+ for (int i = 0; i < outerLoops; i++) {
+ start();
+ for (int j = 0; j < innerLoops; j++) {
+ runnable.run();
+ }
+ stop();
+ sleep();
+ }
+ return this;
+ }
+
+ /**
+ * Time how long it takes to execute runnable.run(). Runs runnable votes
+ * times and returns the Stats of the fastest run. The actual number times
+ * that runnable.run() is executes is enough times so that it runs at least
+ * minThreadholeInMicros but not greater than maxThreadholdInMicro. This
+ * minimizes the chance that long context switches influence the result.
+ *
+ * @param votes is the number of runnable will be executed to determine
+ * fastest run
+ * @param outerLoops is the number of of times the inner loop is run
+ * @param initialInnerLoops is the initial inner loop
+ * @param maxStdDevRetrys if the maxStdDevRatio is exceeded this number of
+ * time the PerfTimerException is thrown.
+ * @param maxStdDevRatio the ratio of the standard deviation of the run and
+ * the time to run.
+ * @param debugLevel DEBUG_LEVEL_NONE, DEBUG_LEVEL_SOME, DEBUG_LEVEL_ALL
+ * @param runnable is the code to test.
+ * @return Stats of the fastest run.
+ */
+ public Stats timeEachAutomatically(int votes, int outerLoops, int initialInnerLoops,
+ double minThresholdInMicros, double maxThresholdInMicros, int maxStdDevRetrys,
+ double maxStdDevRatio, int debugLevel, Runnable runnable) throws PerfTimerException {
+ Stats minStats = null;
+
+ for (int v = 0; v < votes; v++) {
+ boolean successful = false;
+ Stats stats = new Stats();
+ int innerLoops = initialInnerLoops;
+
+ /* Warm up cache */
+ timeEach(stats, outerLoops, initialInnerLoops, runnable);
+
+ for (int stdDevRetrys = 0; stdDevRetrys < maxStdDevRetrys; stdDevRetrys++) {
+ /**
+ * First time may be long enough
+ */
+ timeEach(stats, outerLoops, innerLoops, runnable);
+ analyze(stats, mTimes, outerLoops, debugLevel);
+ double innerLoopTime = stats.getMinInMicros();
+ if ((innerLoopTime >= minThresholdInMicros
+ - ((maxThresholdInMicros - minThresholdInMicros) / 2))) {
+ if (stats.stdDevOk(maxStdDevRatio)) {
+ successful = true;
+ break;
+ } else {
+ stats.incStdDevTooLargeCount();
+ if (debugLevel >= DEBUG_LEVEL_SOME) {
+ log(String.format(
+ "tea: tlc=%d StdDevRatio=%.2f > maxStdDevRatio=%.2f",
+ stats.getStdDevTooLargeCount(), stats.getStdDevRatio(),
+ maxStdDevRatio));
+ }
+ }
+ } else {
+ /**
+ * The initial number of loops is too short find the number
+ * of loops that exceeds maxThresholdInMicros. Then use a
+ * binary search to find the approriate innerLoop value that
+ * is between min/maxThreshold.
+ */
+ innerLoops *= 10;
+ int maxInnerLoops = innerLoops;
+ int minInnerLoops = 1;
+ boolean binarySearch = false;
+ for (int i = 0; i < 10; i++) {
+ timeEach(stats, outerLoops, innerLoops, runnable);
+ analyze(stats, mTimes, outerLoops, debugLevel);
+ innerLoopTime = stats.getMedianInMicros();
+ if ((innerLoopTime >= minThresholdInMicros)
+ && (innerLoopTime <= maxThresholdInMicros)) {
+ if (stats.stdDevOk(maxStdDevRatio)) {
+ successful = true;
+ break;
+ } else {
+ stats.incStdDevTooLargeCount();
+ if (debugLevel >= DEBUG_LEVEL_SOME) {
+ log(String.format(
+ "tea: tlc=%d StdDevRatio=%.2f > maxStdDevRatio=%.2f",
+ stats.getStdDevTooLargeCount(), stats.getStdDevRatio(),
+ maxStdDevRatio));
+ }
+ }
+ } else if (binarySearch) {
+ if ((innerLoopTime < minThresholdInMicros)) {
+ minInnerLoops = innerLoops;
+ } else {
+ maxInnerLoops = innerLoops;
+ }
+ innerLoops = (maxInnerLoops + minInnerLoops) / 2;
+ } else if (innerLoopTime >= maxThresholdInMicros) {
+ /* Found a too large value, change to binary search */
+ binarySearch = true;
+ maxInnerLoops = innerLoops;
+ innerLoops = (maxInnerLoops + minInnerLoops) / 2;
+ } else {
+ innerLoops *= 10;
+ }
+ }
+ if (successful) {
+ break;
+ }
+ }
+ }
+ if (!successful) {
+ /* Couldn't find the number of loops to execute */
+ throw new PerfTimerException();
+ }
+
+ /** Looking for minimum */
+ if ((minStats == null) || (minStats.getTimePerLoop() > stats.getTimePerLoop())) {
+ minStats = stats;
+ }
+ if (debugLevel >= DEBUG_LEVEL_SOME) {
+ log(String.format("minStats.getTimePerLoop=%f minStats: %s", minStats.getTimePerLoop(), minStats));
+ }
+ }
+
+ return minStats;
+ }
+
+ /**
+ * Time how long it takes to execute runnable.run() with a threshold of 1 to
+ * 10ms.
+ *
+ * @param debugLevel DEBUG_LEVEL_NONE, DEBUG_LEVEL_SOME, DEBUG_LEVEL_ALL
+ * @param runnable
+ * @throws PerfTimerException
+ */
+ public Stats timeEachAutomatically(int debugLevel, Runnable runnable)
+ throws PerfTimerException {
+ mStats = timeEachAutomatically(mCr.mVotes, OUTER_LOOPS, 1, mCr.mMinThresholdInMicros,
+ mCr.mMaxThresholdInMicros, mCr.mStdDevRetrys, mCr.mMaxStdDevRatio, debugLevel,
+ runnable);
+ return mStats;
+ }
+
+ /**
+ * Time how long it takes to execute runnable.run() with a threshold of 1 to
+ * 10ms.
+ *
+ * @param runnable
+ * @throws PerfTimerException
+ */
+ public Stats timeEachAutomatically(Runnable runnable) throws PerfTimerException {
+ mStats = timeEachAutomatically(mCr.mVotes, OUTER_LOOPS, 1, mCr.mMinThresholdInMicros,
+ mCr.mMaxThresholdInMicros, mCr.mStdDevRetrys, mCr.mMaxStdDevRatio,
+ DEBUG_LEVEL_NONE, runnable);
+ return mStats;
+ }
+
+ /** Resize the times array */
+ public void resize(int maxCount) {
+ if (maxCount > mTimes.length) {
+ mTimes = new long[maxCount];
+ }
+ }
+
+ /**
+ * Analyze the data calculating the min, max, total, median, mean and
+ * stdDev. The standard deviation is calculated as sqrt(((sum of the squares
+ * of each time) / count) - mean^2)
+ * {@link "http://www.sciencebuddies.org/mentoring/project_data_analysis_variance_std_deviation.shtml"}
+ *
+ * @param debugLevel DEBUG_LEVEL_NONE, DEBUG_LEVEL_SOME, DEBUG_LEVEL_ALL
+ * @return StopWatch
+ */
+ public Stats analyze(Stats stats, long data[], int count, int debugLevel) {
+ if (count > 0) {
+ if (debugLevel >= DEBUG_LEVEL_ALL) {
+ for (int j = 0; j < count; j++) {
+ log(String.format("data[%d]=%,dns", j, data[j]));
+ }
+ }
+ stats.calculate(data, count);
+ } else {
+ stats.init();
+ }
+ if (debugLevel >= DEBUG_LEVEL_SOME) {
+ log("stats: " + stats);
+ }
+ return stats;
+ }
+
+ /**
+ * Calibrate the system and set it for this PerfTimer instance
+ *
+ * @param debugLevel DEBUG_LEVEL_NONE, DEBUG_LEVEL_SOME, DEBUG_LEVEL_ALL
+ * @param precisionInDecimalDigits the precision in number of decimal digits
+ */
+ public CalibrationRec calibrate(int debugLevel, double precisionInDecimalDigits)
+ throws PerfTimerException {
+ int nonZeroCount = 0;
+ Stats stats = new Stats();
+ CalibrationRec cr = new CalibrationRec();
+
+ /* initialize the precision */
+ cr.mPrecisionInDecimalDigits = precisionInDecimalDigits;
+
+ /* Warm up the cache */
+ timeEach(stats, OUTER_LOOPS, 10, mEmptyRunnable);
+
+ /*
+ * Determine the clock stats with at least 20% non-zero unique values.
+ */
+ for (int clockStatsTries = 1; clockStatsTries < 100; clockStatsTries++) {
+ int j;
+ int i;
+ long cur;
+ long prev;
+ long min;
+
+ int innerLoops = clockStatsTries * 10;
+ timeEach(stats, OUTER_LOOPS, innerLoops, mEmptyRunnable);
+ long nonZeroValues[] = new long[mCount];
+ prev = 0;
+ for (nonZeroCount = 0, i = 0; i < mCount; i++) {
+ cur = mTimes[i];
+ if (cur > 0) {
+ nonZeroValues[nonZeroCount++] = cur;
+ }
+ }
+ if (nonZeroCount > (mCount * 0.20)) {
+ // Calculate thresholds
+ analyze(stats, nonZeroValues, nonZeroCount, debugLevel);
+ stats.calculate(nonZeroValues, nonZeroCount);
+ cr.mMinThresholdInMicros = stats.getMeanInMicros()
+ * Math.pow(10, cr.mPrecisionInDecimalDigits);
+ cr.mMaxThresholdInMicros = cr.mMinThresholdInMicros * 2;
+
+ // Set overhead to 0 and time the empty loop then set overhead.
+ cr.mRunnableOverheadInMicros = 0;
+ mClockStats = timeEachAutomatically(mCr.mVotes, OUTER_LOOPS, innerLoops,
+ cr.mMinThresholdInMicros, cr.mMaxThresholdInMicros, mCr.mStdDevRetrys,
+ mCr.mMaxStdDevRatio, debugLevel, mEmptyRunnable);
+ cr.mRunnableOverheadInMicros = mClockStats.getMinInMicros()
+ / mClockStats.getInnerLoops();
+ break;
+ }
+ nonZeroCount = 0;
+ }
+ if (nonZeroCount == 0) {
+ throw new PerfTimerException();
+ }
+ if (debugLevel >= DEBUG_LEVEL_SOME) {
+ log(String.format("calibrate X oh=%.6fus minT=%,.6fus maxT=%,.6fus stats: %s",
+ cr.mRunnableOverheadInMicros, cr.mMinThresholdInMicros,
+ cr.mMaxThresholdInMicros, stats));
+ }
+ mCr = cr;
+ return mCr;
+ }
+
+ /** Calibrate the system and set it for this PerfTimer instance */
+ public CalibrationRec calibrate(double precisionInDecimalDigits) throws PerfTimerException {
+ return calibrate(DEBUG_LEVEL_NONE, precisionInDecimalDigits);
+ }
+
+ /** Calibrate the system and set it for this PerfTimer instance */
+ public CalibrationRec calibrate() throws PerfTimerException {
+ return calibrate(DEBUG_LEVEL_NONE, mCr.mPrecisionInDecimalDigits);
+ }
+
+ /*
+ * Accessors for the private data
+ */
+
+ /** Set calibration record */
+ public void setCalibrationRec(CalibrationRec cr) {
+ mCr = cr;
+ }
+
+ /** Get calibration record */
+ public CalibrationRec getCalibrationRec() {
+ return mCr;
+ }
+
+ /** Number of samples in times array. */
+ public int getCount() {
+ return mCount;
+ }
+
+ /** Minimum value of collected data in microseconds, valid after analyze. */
+ public double getMinInMicros() {
+ return mStats.getMinInMicros();
+ }
+
+ /** Maximum value of collected data in microseconds, valid after analyze. */
+ public double getMaxInMicros() {
+ return mStats.getMaxInMicros();
+ }
+
+ /**
+ * Sum of the values of collected data in microseconds, valid after analyze.
+ */
+ public double getTotalInMicros() {
+ return mStats.getTotalInMicros();
+ }
+
+ /** Sum of the values of collected data in seconds, valid after analyze. */
+ public double getTotalInSecs() {
+ return mStats.getTotalInSecs();
+ }
+
+ /** Sum of the values of collected data in seconds, valid after analyze. */
+ public double getMeanInMicros() {
+ return mStats.getMeanInMicros();
+ }
+
+ /** Median value of collected data in microseconds, valid after analyze. */
+ public double getMedianInMicros() {
+ return mStats.getMedianInMicros();
+ }
+
+ /**
+ * Standard deviation of collected data in microseconds, valid after
+ * analyze.
+ */
+ public double getStdDevInMicros() {
+ return mStats.getStdDevInMicros();
+ }
+
+ /** The mTimes[index] value */
+ public long getTime(int index) {
+ return mTimes[index];
+ }
+
+ /** The mTimes */
+ public long[] getTimes() {
+ return mTimes;
+ }
+
+ /** @return the clock stats as measured in calibrate */
+ public Stats getClockStats() {
+ return mClockStats;
+ }
+
+ /** @return the stats */
+ public Stats getStats() {
+ return mStats;
+ }
+
+ /**
+ * Convert stats to string
+ *
+ * @param debugLevel DEBUG_LEVEL_NONE, DEBUG_LEVEL_SOME, DEBUG_LEVEL_ALL
+ */
+ public String stats(int debugLevel) {
+ int innerLoops = mStats.getInnerLoops();
+ if (mCount == 0) {
+ return String.format("%,.3fus", (getTicks() - mStart) / TICKS_PER_MICROSECOND);
+ } else {
+ if (mCount == 1) {
+ return String.format("%,.3fus", getTime());
+ } else {
+ analyze(mStats, mTimes, mCount, debugLevel);
+ return mStats.toString();
+ }
+ }
+ }
+
+ /**
+ * Convert string
+ */
+ public String stats() {
+ return stats(0);
+ }
+
+ /**
+ * Get time
+ */
+ public double getTime() {
+ int innerLoops = mStats.getInnerLoops();
+ if (mCount == 0) {
+ return (getTicks() - mStart) / TICKS_PER_MICROSECOND;
+ } else {
+ if (mCount == 1) {
+ return mStats.getTotalInMicros();
+ } else {
+ analyze(mStats, mTimes, mCount, DEBUG_LEVEL_NONE);
+ return (mStats.getMinInMicros() / innerLoops) - mCr.mRunnableOverheadInMicros;
+ }
+ }
+ }
+
+ /** Convert to string */
+ @Override
+ public String toString() {
+ return String.format("%,.3fus", getTime());
+ }
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index f49b170..11f05f6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -68,6 +68,7 @@ nobase_include_HEADERS = \
google/protobuf/compiler/parser.h \
google/protobuf/compiler/cpp/cpp_generator.h \
google/protobuf/compiler/java/java_generator.h \
+ google/protobuf/compiler/javamicro/javamicro_generator.h \
google/protobuf/compiler/python/python_generator.h
lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la
@@ -167,6 +168,23 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/java/java_primitive_field.h \
google/protobuf/compiler/java/java_service.cc \
google/protobuf/compiler/java/java_service.h \
+ google/protobuf/compiler/javamicro/javamicro_enum.cc \
+ google/protobuf/compiler/javamicro/javamicro_enum.h \
+ google/protobuf/compiler/javamicro/javamicro_enum_field.cc \
+ google/protobuf/compiler/javamicro/javamicro_enum_field.h \
+ google/protobuf/compiler/javamicro/javamicro_field.cc \
+ google/protobuf/compiler/javamicro/javamicro_field.h \
+ google/protobuf/compiler/javamicro/javamicro_file.cc \
+ google/protobuf/compiler/javamicro/javamicro_file.h \
+ google/protobuf/compiler/javamicro/javamicro_generator.cc \
+ google/protobuf/compiler/javamicro/javamicro_helpers.cc \
+ google/protobuf/compiler/javamicro/javamicro_helpers.h \
+ google/protobuf/compiler/javamicro/javamicro_message.cc \
+ google/protobuf/compiler/javamicro/javamicro_message.h \
+ google/protobuf/compiler/javamicro/javamicro_message_field.cc\
+ google/protobuf/compiler/javamicro/javamicro_message_field.h \
+ google/protobuf/compiler/javamicro/javamicro_primitive_field.cc\
+ google/protobuf/compiler/javamicro/javamicro_primitive_field.h\
google/protobuf/compiler/python/python_generator.cc
bin_PROGRAMS = protoc
diff --git a/src/Makefile.in b/src/Makefile.in
index 1d75dac..1de053d 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -102,7 +102,11 @@ am_libprotoc_la_OBJECTS = code_generator.lo command_line_interface.lo \
cpp_string_field.lo java_enum.lo java_enum_field.lo \
java_extension.lo java_field.lo java_file.lo java_generator.lo \
java_helpers.lo java_message.lo java_message_field.lo \
- java_primitive_field.lo java_service.lo python_generator.lo
+ java_primitive_field.lo java_service.lo javamicro_enum.lo \
+ javamicro_enum_field.lo javamicro_field.lo javamicro_file.lo \
+ javamicro_generator.lo javamicro_helpers.lo \
+ javamicro_message.lo javamicro_message_field.lo \
+ javamicro_primitive_field.lo python_generator.lo
libprotoc_la_OBJECTS = $(am_libprotoc_la_OBJECTS)
libprotoc_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
@@ -280,6 +284,7 @@ am__nobase_include_HEADERS_DIST = google/protobuf/stubs/common.h \
google/protobuf/compiler/parser.h \
google/protobuf/compiler/cpp/cpp_generator.h \
google/protobuf/compiler/java/java_generator.h \
+ google/protobuf/compiler/javamicro/javamicro_generator.h \
google/protobuf/compiler/python/python_generator.h
nobase_includeHEADERS_INSTALL = $(install_sh_DATA)
HEADERS = $(nobase_include_HEADERS)
@@ -467,6 +472,7 @@ nobase_include_HEADERS = \
google/protobuf/compiler/parser.h \
google/protobuf/compiler/cpp/cpp_generator.h \
google/protobuf/compiler/java/java_generator.h \
+ google/protobuf/compiler/javamicro/javamicro_generator.h \
google/protobuf/compiler/python/python_generator.h
lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la
@@ -565,6 +571,23 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/java/java_primitive_field.h \
google/protobuf/compiler/java/java_service.cc \
google/protobuf/compiler/java/java_service.h \
+ google/protobuf/compiler/javamicro/javamicro_enum.cc \
+ google/protobuf/compiler/javamicro/javamicro_enum.h \
+ google/protobuf/compiler/javamicro/javamicro_enum_field.cc \
+ google/protobuf/compiler/javamicro/javamicro_enum_field.h \
+ google/protobuf/compiler/javamicro/javamicro_field.cc \
+ google/protobuf/compiler/javamicro/javamicro_field.h \
+ google/protobuf/compiler/javamicro/javamicro_file.cc \
+ google/protobuf/compiler/javamicro/javamicro_file.h \
+ google/protobuf/compiler/javamicro/javamicro_generator.cc \
+ google/protobuf/compiler/javamicro/javamicro_helpers.cc \
+ google/protobuf/compiler/javamicro/javamicro_helpers.h \
+ google/protobuf/compiler/javamicro/javamicro_message.cc \
+ google/protobuf/compiler/javamicro/javamicro_message.h \
+ google/protobuf/compiler/javamicro/javamicro_message_field.cc\
+ google/protobuf/compiler/javamicro/javamicro_message_field.h \
+ google/protobuf/compiler/javamicro/javamicro_primitive_field.cc\
+ google/protobuf/compiler/javamicro/javamicro_primitive_field.h\
google/protobuf/compiler/python/python_generator.cc
protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la
@@ -868,6 +891,15 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_message_field.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_primitive_field.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_service.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_enum.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_enum_field.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_field.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_file.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_generator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_helpers.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_message.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_message_field.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/javamicro_primitive_field.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message_lite.Plo@am__quote@
@@ -1369,6 +1401,69 @@ java_service.lo: google/protobuf/compiler/java/java_service.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o java_service.lo `test -f 'google/protobuf/compiler/java/java_service.cc' || echo '$(srcdir)/'`google/protobuf/compiler/java/java_service.cc
+javamicro_enum.lo: google/protobuf/compiler/javamicro/javamicro_enum.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_enum.lo -MD -MP -MF $(DEPDIR)/javamicro_enum.Tpo -c -o javamicro_enum.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_enum.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_enum.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/javamicro_enum.Tpo $(DEPDIR)/javamicro_enum.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_enum.cc' object='javamicro_enum.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_enum.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_enum.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_enum.cc
+
+javamicro_enum_field.lo: google/protobuf/compiler/javamicro/javamicro_enum_field.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_enum_field.lo -MD -MP -MF $(DEPDIR)/javamicro_enum_field.Tpo -c -o javamicro_enum_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_enum_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_enum_field.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/javamicro_enum_field.Tpo $(DEPDIR)/javamicro_enum_field.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_enum_field.cc' object='javamicro_enum_field.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_enum_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_enum_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_enum_field.cc
+
+javamicro_field.lo: google/protobuf/compiler/javamicro/javamicro_field.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_field.lo -MD -MP -MF $(DEPDIR)/javamicro_field.Tpo -c -o javamicro_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_field.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/javamicro_field.Tpo $(DEPDIR)/javamicro_field.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_field.cc' object='javamicro_field.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_field.cc
+
+javamicro_file.lo: google/protobuf/compiler/javamicro/javamicro_file.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_file.lo -MD -MP -MF $(DEPDIR)/javamicro_file.Tpo -c -o javamicro_file.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_file.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_file.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/javamicro_file.Tpo $(DEPDIR)/javamicro_file.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_file.cc' object='javamicro_file.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_file.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_file.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_file.cc
+
+javamicro_generator.lo: google/protobuf/compiler/javamicro/javamicro_generator.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_generator.lo -MD -MP -MF $(DEPDIR)/javamicro_generator.Tpo -c -o javamicro_generator.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_generator.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/javamicro_generator.Tpo $(DEPDIR)/javamicro_generator.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_generator.cc' object='javamicro_generator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_generator.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_generator.cc
+
+javamicro_helpers.lo: google/protobuf/compiler/javamicro/javamicro_helpers.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_helpers.lo -MD -MP -MF $(DEPDIR)/javamicro_helpers.Tpo -c -o javamicro_helpers.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_helpers.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_helpers.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/javamicro_helpers.Tpo $(DEPDIR)/javamicro_helpers.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_helpers.cc' object='javamicro_helpers.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_helpers.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_helpers.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_helpers.cc
+
+javamicro_message.lo: google/protobuf/compiler/javamicro/javamicro_message.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_message.lo -MD -MP -MF $(DEPDIR)/javamicro_message.Tpo -c -o javamicro_message.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_message.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_message.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/javamicro_message.Tpo $(DEPDIR)/javamicro_message.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_message.cc' object='javamicro_message.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_message.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_message.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_message.cc
+
+javamicro_message_field.lo: google/protobuf/compiler/javamicro/javamicro_message_field.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_message_field.lo -MD -MP -MF $(DEPDIR)/javamicro_message_field.Tpo -c -o javamicro_message_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_message_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_message_field.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/javamicro_message_field.Tpo $(DEPDIR)/javamicro_message_field.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_message_field.cc' object='javamicro_message_field.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_message_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_message_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_message_field.cc
+
+javamicro_primitive_field.lo: google/protobuf/compiler/javamicro/javamicro_primitive_field.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT javamicro_primitive_field.lo -MD -MP -MF $(DEPDIR)/javamicro_primitive_field.Tpo -c -o javamicro_primitive_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_primitive_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_primitive_field.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/javamicro_primitive_field.Tpo $(DEPDIR)/javamicro_primitive_field.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='google/protobuf/compiler/javamicro/javamicro_primitive_field.cc' object='javamicro_primitive_field.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o javamicro_primitive_field.lo `test -f 'google/protobuf/compiler/javamicro/javamicro_primitive_field.cc' || echo '$(srcdir)/'`google/protobuf/compiler/javamicro/javamicro_primitive_field.cc
+
python_generator.lo: google/protobuf/compiler/python/python_generator.cc
@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT python_generator.lo -MD -MP -MF $(DEPDIR)/python_generator.Tpo -c -o python_generator.lo `test -f 'google/protobuf/compiler/python/python_generator.cc' || echo '$(srcdir)/'`google/protobuf/compiler/python/python_generator.cc
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/python_generator.Tpo $(DEPDIR)/python_generator.Plo
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_enum.cc b/src/google/protobuf/compiler/javamicro/javamicro_enum.cc
new file mode 100644
index 0000000..d74a149
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_enum.cc
@@ -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/javamicro/javamicro_params.h>
+#include <google/protobuf/compiler/javamicro/javamicro_enum.h>
+#include <google/protobuf/compiler/javamicro/javamicro_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 javamicro {
+
+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 javamicro
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_enum.h b/src/google/protobuf/compiler/javamicro/javamicro_enum.h
new file mode 100644
index 0000000..9cf226f
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_enum.h
@@ -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/javamicro/javamicro_params.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javamicro {
+
+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 javamicro
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_enum_field.cc b/src/google/protobuf/compiler/javamicro/javamicro_enum_field.cc
new file mode 100644
index 0000000..0ff49a3
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_enum_field.cc
@@ -0,0 +1,333 @@
+// 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/javamicro/javamicro_enum_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/javamicro/javamicro_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 javamicro {
+
+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_,
+ "private boolean has$capitalized_name$;\n"
+ "private int $name$_ = $default$;\n"
+ "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
+ "public int get$capitalized_name$() { return $name$_; }\n"
+ "public $message_name$ set$capitalized_name$(int value) {\n"
+ " has$capitalized_name$ = true;\n"
+ " $name$_ = value;\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " has$capitalized_name$ = false;\n"
+ " $name$_ = $default$;\n"
+ " return this;\n"
+ "}\n");
+}
+
+void EnumFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "what is other??"
+ "if (other.has$capitalized_name$()) {\n"
+ " set$capitalized_name$(other.get$capitalized_name$());\n"
+ "}\n");
+}
+
+void EnumFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ " set$capitalized_name$(input.readInt32());\n");
+}
+
+void EnumFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (has$capitalized_name$()) {\n"
+ " output.writeInt32($number$, get$capitalized_name$());\n"
+ "}\n");
+}
+
+void EnumFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (has$capitalized_name$()) {\n"
+ " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
+ " .computeInt32Size($number$, get$capitalized_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_);
+ if (descriptor_->options().packed()) {
+ GOOGLE_LOG(FATAL) << "MicroRuntime does not support packed";
+ }
+}
+
+RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
+
+void RepeatedEnumFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+ if (params_.java_use_vector()) {
+ printer->Print(variables_,
+ "private java.util.Vector $name$_ = new java.util.Vector();\n"
+ "public java.util.Vector get$capitalized_name$List() {\n"
+ " return $name$_;\n"
+ "}\n"
+ "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
+ "public int get$capitalized_name$(int index) {\n"
+ " return ((Integer)$name$_.elementAt(index)).intValue();\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$(int index, int value) {\n"
+ " $name$_.setElementAt(new Integer(value), index);\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ add$capitalized_name$(int value) {\n"
+ " $name$_.addElement(new Integer(value));\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " $name$_.removeAllElements();\n"
+ " return this;\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "private java.util.List<Integer> $name$_ =\n"
+ " java.util.Collections.emptyList();\n"
+ "public java.util.List<Integer> get$capitalized_name$List() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n"
+ "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
+ "public int get$capitalized_name$(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$(int index, int value) {\n"
+ " $name$_.set(index, value);\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ add$capitalized_name$(int value) {\n"
+ " if ($name$_.isEmpty()) {\n"
+ " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
+ " }\n"
+ " $name$_.add(value);\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " $name$_ = java.util.Collections.emptyList();\n"
+ " return this;\n"
+ "}\n");
+ }
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "private int $name$MemoizedSerializedSize;\n");
+ }
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ if (params_.java_use_vector()) {
+ printer->Print(variables_,
+ "if (other.$name$_.size() != 0) {\n"
+ " for (int i = 0; i < other.$name$_.size(); i++)) {\n"
+ " result.$name$_.addElement(other.$name$_.elementAt(i));\n"
+ " }\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "if (!other.$name$_.isEmpty()) {\n"
+ " if (result.$name$_.isEmpty()) {\n"
+ " result.$name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
+ " }\n"
+ " result.$name$_.addAll(other.$name$_);\n"
+ "}\n");
+ }
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ // If packed, set up the while loop
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int oldLimit = input.pushLimit(length);\n"
+ "while(input.getBytesUntilLimit() > 0) {\n");
+ printer->Indent();
+ }
+
+ // Read and store the enum
+ printer->Print(variables_,
+ " add$capitalized_name$(input.readInt32());\n");
+
+ if (descriptor_->options().packed()) {
+ printer->Outdent();
+ printer->Print(variables_,
+ "}\n"
+ "input.popLimit(oldLimit);\n");
+ }
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (get$capitalized_name$List().size() > 0) {\n"
+ " output.writeRawVarint32($tag$);\n"
+ " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+ "}\n");
+ if (params_.java_use_vector()) {
+ printer->Print(variables_,
+ "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
+ " output.writeRawVarint32(get$capitalized_name$(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for ($type$ element : get$capitalized_name$List()) {\n"
+ " output.writeRawVarint32(element.getNumber());\n"
+ "}\n");
+ }
+ } else {
+ if (params_.java_use_vector()) {
+ printer->Print(variables_,
+ "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
+ " output.writeInt32($number$, (int)get$capitalized_name$(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for (java.lang.Integer element : get$capitalized_name$List()) {\n"
+ " output.writeInt32($number$, element);\n"
+ "}\n");
+ }
+ }
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "{\n"
+ " int dataSize = 0;\n");
+ printer->Indent();
+ if (params_.java_use_vector()) {
+ printer->Print(variables_,
+ "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
+ " dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n"
+ " .computeInt32SizeNoTag(get$capitalized_name$(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for (java.lang.Integer element : get$capitalized_name$List()) {\n"
+ " dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n"
+ " .computeInt32SizeNoTag(element);\n"
+ "}\n");
+ }
+ printer->Print(
+ "size += dataSize;\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (get$capitalized_name$List().size() != 0) {"
+ " size += $tag_size$;\n"
+ " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
+ " .computeRawVarint32Size(dataSize);\n"
+ "}");
+ } else {
+ printer->Print(variables_,
+ "size += $tag_size$ * get$capitalized_name$List().size();\n");
+ }
+
+ // cache the data size for packed fields.
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "$name$MemoizedSerializedSize = dataSize;\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+string RepeatedEnumFieldGenerator::GetBoxedType() const {
+ return ClassName(params_, descriptor_->enum_type());
+}
+
+} // namespace javamicro
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_enum_field.h b/src/google/protobuf/compiler/javamicro/javamicro_enum_field.h
new file mode 100644
index 0000000..ab671c1
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_enum_field.h
@@ -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/javamicro/javamicro_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javamicro {
+
+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 javamicro
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_field.cc b/src/google/protobuf/compiler/javamicro/javamicro_field.cc
new file mode 100644
index 0000000..a2ea4f9
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_field.cc
@@ -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/javamicro/javamicro_field.h>
+#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
+#include <google/protobuf/compiler/javamicro/javamicro_primitive_field.h>
+#include <google/protobuf/compiler/javamicro/javamicro_enum_field.h>
+#include <google/protobuf/compiler/javamicro/javamicro_message_field.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javamicro {
+
+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 javamicro
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_field.h b/src/google/protobuf/compiler/javamicro/javamicro_field.h
new file mode 100644
index 0000000..1530778
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_field.h
@@ -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/javamicro/javamicro_params.h>
+
+namespace google {
+namespace protobuf {
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javamicro {
+
+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 javamicro
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_file.cc b/src/google/protobuf/compiler/javamicro/javamicro_file.cc
new file mode 100644
index 0000000..0985538
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_file.cc
@@ -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/javamicro/javamicro_file.h>
+#include <google/protobuf/compiler/javamicro/javamicro_enum.h>
+#include <google/protobuf/compiler/javamicro/javamicro_helpers.h>
+#include <google/protobuf/compiler/javamicro/javamicro_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 javamicro {
+
+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 MICRO_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 MICRO_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 MICRO_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 MICRO_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 javamicro
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_file.h b/src/google/protobuf/compiler/javamicro/javamicro_file.h
new file mode 100644
index 0000000..430172a
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_file.h
@@ -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/javamicro/javamicro_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 javamicro {
+
+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 javamicro
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_generator.cc b/src/google/protobuf/compiler/javamicro/javamicro_generator.cc
new file mode 100644
index 0000000..bfba8c5
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_generator.cc
@@ -0,0 +1,209 @@
+// 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/javamicro/javamicro_params.h>
+#include <google/protobuf/compiler/javamicro/javamicro_generator.h>
+#include <google/protobuf/compiler/javamicro/javamicro_file.h>
+#include <google/protobuf/compiler/javamicro/javamicro_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 javamicro {
+
+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));
+ }
+}
+
+JavaMicroGenerator::JavaMicroGenerator() {}
+JavaMicroGenerator::~JavaMicroGenerator() {}
+
+bool JavaMicroGenerator::Generate(const FileDescriptor* file,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error) const {
+ vector<pair<string, string> > options;
+
+// GOOGLE_LOG(INFO) << "wink: JavaMicroGenerator::Generate INFO";
+// GOOGLE_LOG(WARNING) << "wink: JavaMicroGenerator::Generate WARNING";
+// GOOGLE_LOG(ERROR) << "wink: JavaMicroGenerator::Generate ERROR";
+// GOOGLE_LOG(FATAL) << "wink: JavaMicroGenerator::Generate";
+
+ 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++) {
+ // GOOGLE_LOG(WARNING) << "first=" << options[i].first
+ // << " second=" << options[i].second;
+ if (options[i].first == "output_list_file") {
+ output_list_file = options[i].second;
+ } else if (options[i].first == "opt") {
+ if (options[i].second == "speed") {
+ params.set_optimization(JAVAMICRO_OPT_SPEED);
+ } else if (options[i].second == "space") {
+ params.set_optimization(JAVAMICRO_OPT_SPACE);
+ } else {
+ *error = "Unknown javamicro generator option: opt="
+ + options[i].second + " expecting opt=space or opt=speed";
+ return false;
+ }
+ } 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 if (options[i].first == "java_use_vector") {
+ params.set_java_use_vector(options[i].second == "true");
+ } else {
+ *error = "Ignore unknown javamicro generator option: " + options[i].first;
+ }
+ }
+
+#if 0
+ GOOGLE_LOG(WARNING) << "optimization()=" << params.optimization();
+ GOOGLE_LOG(WARNING) << "java_multiple_files()=" << params.java_multiple_files();
+ GOOGLE_LOG(WARNING) << "java_use_vector()=" << params.java_use_vector();
+
+ GOOGLE_LOG(WARNING) << "----------";
+ for (Params::NameMap::const_iterator it = params.java_packages().begin();
+ it != params.java_packages().end();
+ ++it) {
+ GOOGLE_LOG(WARNING) << "cn.filename=" << it->first << " package=" << it->second;
+ }
+ for (Params::NameMap::const_iterator it = params.java_outer_classnames().begin();
+ it != params.java_outer_classnames().end();
+ ++it) {
+ GOOGLE_LOG(WARNING) << "cn.filename=" << it->first << " classname=" << it->second;
+ }
+ GOOGLE_LOG(WARNING) << "==========";
+
+#endif
+
+ // -----------------------------------------------------------------
+
+ 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
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_generator.h b/src/google/protobuf/compiler/javamicro/javamicro_generator.h
new file mode 100644
index 0000000..a1c33b7
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_generator.h
@@ -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 micro code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MICRO_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MICRO_GENERATOR_H__
+
+#include <string>
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javamicro {
+
+// CodeGenerator implementation which generates Java micro code. If you create your
+// own protocol compiler binary and you want it to support Java output for the
+// micro runtime, you can do so by registering an instance of this CodeGenerator with
+// the CommandLineInterface in your main() function.
+class LIBPROTOC_EXPORT JavaMicroGenerator : public CodeGenerator {
+ public:
+ JavaMicroGenerator();
+ ~JavaMicroGenerator();
+
+ // implements CodeGenerator ----------------------------------------
+ bool Generate(const FileDescriptor* file,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaMicroGenerator);
+};
+
+} // namespace javamicro
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MICRO_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_helpers.cc b/src/google/protobuf/compiler/javamicro/javamicro_helpers.cc
new file mode 100644
index 0000000..11ba71a
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_helpers.cc
@@ -0,0 +1,381 @@
+// 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/javamicro/javamicro_helpers.h>
+#include <google/protobuf/compiler/javamicro/javamicro_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 javamicro {
+
+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();
+ int last_period = full_name.find_last_of('.');
+ int first_period = full_name.find_first_of('.');
+
+ // Remove class_name as we're using public static final int's not enums
+ string base_name = full_name.substr(0, full_name.find_last_of('.'));
+
+ if (!file->package().empty()) {
+ // Remove package name.
+ int offset = first_period;
+ if (last_period > first_period) {
+ // There was two or more periods so we need to remove this one too.
+ offset += 1;
+ }
+ base_name = base_name.substr(offset);
+ }
+
+ if (params.has_java_package(file_name)) {
+ result += params.java_package(file_name);
+ }
+ if (params.has_java_outer_classname(file_name)) {
+ result += ".";
+ result += params.java_outer_classname(file_name);
+ }
+ if (!base_name.empty()) {
+ result += ".";
+ result += base_name;
+ }
+ return result;
+}
+
+string FieldConstantName(const FieldDescriptor *field) {
+ string name = field->name() + "_FIELD_NUMBER";
+ 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 "com.google.protobuf.micro.ByteStringMicro";
+ 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;
+}
+
+bool AllAscii(const string& text) {
+ for (int i = 0; i < text.size(); i++) {
+ if ((text[i] & 0x80) != 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+string DefaultValue(const Params& params, const FieldDescriptor* 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->type() == FieldDescriptor::TYPE_BYTES) {
+ if (field->has_default_value()) {
+ // See comments in Internal.java for gory details.
+ return strings::Substitute(
+ "com.google.protobuf.micro.ByteStringMicro.copyFromUtf8(\"$0\")",
+ CEscape(field->default_value_string()));
+ } else {
+ return "com.google.protobuf.micro.ByteStringMicro.EMPTY";
+ }
+ } else {
+ if (AllAscii(field->default_value_string())) {
+ // All chars are ASCII. In this case CEscape() works fine.
+ return "\"" + CEscape(field->default_value_string()) + "\"";
+ } else {
+ // See comments in Internal.java for gory details.
+ // BUG: Internal NOT SUPPORTED need to fix!!
+ return strings::Substitute(
+ "com.google.protobuf.micro.Internal.stringDefaultValue(\"$0\")",
+ CEscape(field->default_value_string()));
+ }
+ }
+
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return ClassName(params, field->enum_type()) + "." +
+ field->default_value_enum()->name();
+
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return ClassName(params, field->message_type()) + ".getDefaultInstance()";
+
+ // No default because we want the compiler to complain if any new
+ // types are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return "";
+}
+
+} // namespace javamicro
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_helpers.h b/src/google/protobuf/compiler/javamicro/javamicro_helpers.h
new file mode 100644
index 0000000..eeddbf9
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_helpers.h
@@ -0,0 +1,128 @@
+// 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/javamicro/javamicro_params.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javamicro {
+
+// 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);
+
+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 DefaultValue(const Params& params, const FieldDescriptor* field);
+
+} // namespace javamicro
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_message.cc b/src/google/protobuf/compiler/javamicro/javamicro_message.cc
new file mode 100644
index 0000000..7fc6c3d
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_message.cc
@@ -0,0 +1,474 @@
+// 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/javamicro/javamicro_message.h>
+#include <google/protobuf/compiler/javamicro/javamicro_enum.h>
+#include <google/protobuf/compiler/javamicro/javamicro_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 javamicro {
+
+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);
+}
+
+// Returns true if the message type has any required fields. If it doesn't,
+// we can optimize out calls to its isInitialized() method.
+//
+// already_seen is used to avoid checking the same type multiple times
+// (and also to protect against recursion).
+static bool HasRequiredFields(
+ const Descriptor* type,
+ hash_set<const Descriptor*>* already_seen) {
+ if (already_seen->count(type) > 0) {
+ // The type is already in cache. This means that either:
+ // a. The type has no required fields.
+ // b. We are in the midst of checking if the type has required fields,
+ // somewhere up the stack. In this case, we know that if the type
+ // has any required fields, they'll be found when we return to it,
+ // and the whole call to HasRequiredFields() will return true.
+ // Therefore, we don't have to check if this type has required fields
+ // here.
+ return false;
+ }
+ already_seen->insert(type);
+
+ // If the type has extensions, an extension with message type could contain
+ // required fields, so we have to be conservative and assume such an
+ // extension exists.
+ if (type->extension_range_count() > 0) return true;
+
+ for (int i = 0; i < type->field_count(); i++) {
+ const FieldDescriptor* field = type->field(i);
+ if (field->is_required()) {
+ return true;
+ }
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (HasRequiredFields(field->message_type(), already_seen)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool HasRequiredFields(const Descriptor* type) {
+ hash_set<const Descriptor*> already_seen;
+ return HasRequiredFields(type, &already_seen);
+}
+
+} // 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 MICRO_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 MICRO_RUNTIME\n";
+ }
+
+ printer->Print(
+ "public $modifiers$ final class $classname$ extends\n"
+ " com.google.protobuf.micro.MessageMicro {\n",
+ "modifiers", is_own_file ? "" : "static",
+ "classname", descriptor_->name());
+ printer->Indent();
+ printer->Print(
+ "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));
+ printer->Print("public static final int $constant_name$ = $number$;\n",
+ "constant_name", FieldConstantName(descriptor_->field(i)),
+ "number", SimpleItoa(descriptor_->field(i)->number()));
+ field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
+ printer->Print("\n");
+ }
+
+ GenerateClear(printer);
+ GenerateIsInitialized(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 MICRO_RUNTIME\n";
+ }
+
+ printer->Print(
+ "public void writeTo(com.google.protobuf.micro.CodedOutputStreamMicro output)\n"
+ " throws java.io.IOException {\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"
+ "public int getCachedSize() {\n"
+ " if (cachedSize < 0) {\n"
+ " // getSerializedSize sets cachedSize\n"
+ " getSerializedSize();\n"
+ " }\n"
+ " return cachedSize;\n"
+ "}\n"
+ "\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_));
+
+ if (params_.java_use_vector()) {
+ printer->Print(
+ "public com.google.protobuf.micro.MessageMicro mergeFrom(\n"
+ " com.google.protobuf.micro.CodedInputStreamMicro input)\n"
+ " throws java.io.IOException {\n",
+ "classname", descriptor_->name());
+ } else {
+ printer->Print(
+ "public $classname$ mergeFrom(\n"
+ " com.google.protobuf.micro.CodedInputStreamMicro 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 (!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.micro.InvalidProtocolBufferMicroException {\n"
+ " return ($classname$) (new $classname$().mergeFrom(data));\n"
+ "}\n"
+ "\n"
+ "public $static$ $classname$ parseFrom(\n"
+ " com.google.protobuf.micro.CodedInputStreamMicro input)\n"
+ " throws java.io.IOException {\n"
+ " return ($classname$) (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);
+
+ printer->Print(
+ "clear$name$();\n",
+ "name", UnderscoresToCapitalizedCamelCase(field));
+ }
+
+ printer->Outdent();
+ printer->Print(
+ " cachedSize = -1;\n"
+ " return this;\n"
+ "}\n"
+ "\n");
+}
+
+
+void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
+ printer->Print(
+ "public final boolean isInitialized() {\n");
+ printer->Indent();
+
+ // Check that all required fields in this message are set.
+ // TODO(kenton): We can optimize this when we switch to putting all the
+ // "has" fields into a single bitfield.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+
+ if (field->is_required()) {
+ printer->Print(
+ "if (!has$name$) return false;\n",
+ "name", UnderscoresToCapitalizedCamelCase(field));
+ }
+ }
+
+ // Now check that all embedded messages are initialized.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ HasRequiredFields(field->message_type())) {
+ switch (field->label()) {
+ case FieldDescriptor::LABEL_REQUIRED:
+ printer->Print(
+ "if (!get$name$().isInitialized()) return false;\n",
+ "type", ClassName(params_, field->message_type()),
+ "name", UnderscoresToCapitalizedCamelCase(field));
+ break;
+ case FieldDescriptor::LABEL_OPTIONAL:
+ printer->Print(
+ "if (has$name$()) {\n"
+ " if (!get$name$().isInitialized()) return false;\n"
+ "}\n",
+ "type", ClassName(params_, field->message_type()),
+ "name", UnderscoresToCapitalizedCamelCase(field));
+ break;
+ case FieldDescriptor::LABEL_REPEATED:
+ if (params_.java_use_vector()) {
+ printer->Print(
+ "for (int i = 0; i < get$name$List().size(); i++) {\n"
+ " if (get$name$(i).isInitialized()) return false;\n"
+ "}\n",
+ "type", ClassName(params_, field->message_type()),
+ "name", UnderscoresToCapitalizedCamelCase(field));
+ } else {
+ printer->Print(
+ "for ($type$ element : get$name$List()) {\n"
+ " if (!element.isInitialized()) return false;\n"
+ "}\n",
+ "type", ClassName(params_, field->message_type()),
+ "name", UnderscoresToCapitalizedCamelCase(field));
+ }
+ break;
+ }
+ }
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "if (!extensionsAreInitialized()) return false;\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ " return true;\n"
+ "}\n"
+ "\n");
+}
+
+// ===================================================================
+
+} // namespace javamicro
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_message.h b/src/google/protobuf/compiler/javamicro/javamicro_message.h
new file mode 100644
index 0000000..f44c7a7
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_message.h
@@ -0,0 +1,93 @@
+// 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/javamicro/javamicro_params.h>
+#include <google/protobuf/compiler/javamicro/javamicro_field.h>
+
+namespace google {
+namespace protobuf {
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace javamicro {
+
+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);
+ void GenerateIsInitialized(io::Printer* printer);
+
+ const Params& params_;
+ const Descriptor* descriptor_;
+ FieldGeneratorMap field_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
+};
+
+} // namespace javamicro
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_message_field.cc b/src/google/protobuf/compiler/javamicro/javamicro_message_field.cc
new file mode 100644
index 0000000..103c302
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_message_field.cc
@@ -0,0 +1,302 @@
+// 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/javamicro/javamicro_message_field.h>
+#include <google/protobuf/compiler/javamicro/javamicro_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 javamicro {
+
+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();
+}
+
+} // 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_,
+ "private boolean has$capitalized_name$;\n"
+// "private $type$ $name$_ = null;\n"
+// "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
+// "public $type$ get$capitalized_name$() { return $name$_; }\n"
+ "private $type$ $name$_ = null;\n"
+ "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
+ "public $type$ get$capitalized_name$() { return $name$_; }\n"
+ "public $message_name$ set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " has$capitalized_name$ = true;\n"
+ " $name$_ = value;\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " has$capitalized_name$ = false;\n"
+ " $name$_ = null;\n"
+ " return this;\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (other.has$capitalized_name$()) {\n"
+ " merge$capitalized_name$(other.get$capitalized_name$());\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$type$ value = new $type$();\n");
+
+ if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ "input.readGroup(value, $number$);\n");
+ } else {
+ printer->Print(variables_,
+ "input.readMessage(value);\n");
+ }
+
+ printer->Print(variables_,
+ "set$capitalized_name$(value);\n");
+}
+
+void MessageFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (has$capitalized_name$()) {\n"
+ " output.write$group_or_message$($number$, get$capitalized_name$());\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (has$capitalized_name$()) {\n"
+ " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
+ " .compute$group_or_message$Size($number$, get$capitalized_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 {
+ if (params_.java_use_vector()) {
+ printer->Print(variables_,
+ "private java.util.Vector $name$_ = new java.util.Vector();\n"
+ "public java.util.Vector get$capitalized_name$List() {\n"
+ " return $name$_;\n"
+ "}\n"
+ "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
+ "public $type$ get$capitalized_name$(int index) {\n"
+ " return ($type$) $name$_.elementAt(index);\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " $name$_.setElementAt(value, index);\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ add$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " $name$_.addElement(value);\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " $name$_.removeAllElements();\n"
+ " return this;\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "private java.util.List<$type$> $name$_ =\n"
+ " java.util.Collections.emptyList();\n"
+ "public java.util.List<$type$> get$capitalized_name$List() {\n"
+ " return $name$_;\n"
+ "}\n"
+ "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
+ "public $type$ get$capitalized_name$(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " $name$_.set(index, value);\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ add$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " if ($name$_.isEmpty()) {\n"
+ " $name$_ = new java.util.ArrayList<$type$>();\n"
+ " }\n"
+ " $name$_.add(value);\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " $name$_ = java.util.Collections.emptyList();\n"
+ " return this;\n"
+ "}\n");
+ }
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ if (params_.java_use_vector()) {
+ printer->Print(variables_,
+ "if (other.$name$_.size() != 0) {\n"
+ " for (int i = 0; i < other.$name$_.size(); i++) {\n"
+ " result.$name$_.addElement(other.$name$_.elementAt(i));\n"
+ " }\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "if (!other.$name$_.isEmpty()) {\n"
+ " if (result.$name$_.isEmpty()) {\n"
+ " result.$name$_ = new java.util.ArrayList<$type$>();\n"
+ " }\n"
+ " result.$name$_.addAll(other.$name$_);\n"
+ "}\n");
+ }
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$type$ value = new $type$();\n");
+
+ if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ "input.readGroup(value, $number$);\n");
+ } else {
+ printer->Print(variables_,
+ "input.readMessage(value);\n");
+ }
+
+ printer->Print(variables_,
+ "add$capitalized_name$(value);\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (params_.java_use_vector()) {
+ printer->Print(variables_,
+ "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
+ " output.write$group_or_message$($number$, get$capitalized_name$(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for ($type$ element : get$capitalized_name$List()) {\n"
+ " output.write$group_or_message$($number$, element);\n"
+ "}\n");
+ }
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ if (params_.java_use_vector()) {
+ printer->Print(variables_,
+ "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
+ " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
+ " .compute$group_or_message$Size($number$, get$capitalized_name$(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for ($type$ element : get$capitalized_name$List()) {\n"
+ " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
+ " .compute$group_or_message$Size($number$, element);\n"
+ "}\n");
+ }
+}
+
+string RepeatedMessageFieldGenerator::GetBoxedType() const {
+ return ClassName(params_, descriptor_->message_type());
+}
+
+} // namespace javamicro
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_message_field.h b/src/google/protobuf/compiler/javamicro/javamicro_message_field.h
new file mode 100644
index 0000000..a32aa4e
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_message_field.h
@@ -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/javamicro/javamicro_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javamicro {
+
+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 javamicro
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_params.h b/src/google/protobuf/compiler/javamicro/javamicro_params.h
new file mode 100644
index 0000000..a4a72b7
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_params.h
@@ -0,0 +1,143 @@
+// 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_JAVAMICRO_JAVAMICRO_PARAMS_H_
+#define PROTOBUF_COMPILER_JAVAMICRO_JAVAMICRO_PARAMS_H_
+
+#include <map>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javamicro {
+
+enum eOptimization { JAVAMICRO_OPT_SPEED, JAVAMICRO_OPT_SPACE, JAVAMICRO_OPT_DEFAULT = JAVAMICRO_OPT_SPACE };
+
+// Parameters for used by the generators
+class Params {
+ public:
+ typedef map<string, string> NameMap;
+ private:
+ string empty_;
+ string base_name_;
+ eOptimization optimization_;
+ bool java_multiple_files_;
+ bool java_use_vector_;
+ NameMap java_packages_;
+ NameMap java_outer_classnames_;
+
+ public:
+ Params(const string & base_name) :
+ empty_(""),
+ base_name_(base_name),
+ optimization_(JAVAMICRO_OPT_DEFAULT),
+ java_multiple_files_(false),
+ java_use_vector_(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_optimization(eOptimization optimization) {
+ optimization_ = optimization;
+ }
+ eOptimization optimization() const {
+ return optimization_;
+ }
+
+ void set_java_multiple_files(bool value) {
+ java_multiple_files_ = value;
+ }
+ bool java_multiple_files() const {
+ return java_multiple_files_;
+ }
+
+ void set_java_use_vector(bool value) {
+ java_use_vector_ = value;
+ }
+ bool java_use_vector() const {
+ return java_use_vector_;
+ }
+
+};
+
+} // namespace javamicro
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // PROTOBUF_COMPILER_JAVAMICRO_JAVAMICRO_PARAMS_H_
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_primitive_field.cc b/src/google/protobuf/compiler/javamicro/javamicro_primitive_field.cc
new file mode 100644
index 0000000..d6daa44
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_primitive_field.cc
@@ -0,0 +1,660 @@
+// 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/javamicro/javamicro_primitive_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/javamicro/javamicro_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 javamicro {
+
+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 "com.google.protobuf.micro.ByteStringMicro";
+ 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;
+}
+
+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 IsStringUtf8Handling(const FieldDescriptor* descriptor,
+ const Params params) {
+ return ((params.optimization() == JAVAMICRO_OPT_SPEED)
+ && (GetJavaType(descriptor) == JAVATYPE_STRING));
+}
+
+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());
+ if (IsStringUtf8Handling(descriptor, params)) {
+ (*variables)["type"] = "com.google.protobuf.micro.StringUtf8Micro";
+ string defaultValue = DefaultValue(params, descriptor);
+ if (defaultValue == "\"\"") {
+ (*variables)["default"] =
+ "com.google.protobuf.micro.StringUtf8Micro.EMPTY";
+ } else {
+ (*variables)["default"] = "new com.google.protobuf.micro.StringUtf8Micro("
+ + defaultValue + ")";
+ }
+ } else {
+ (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
+ (*variables)["default"] = DefaultValue(params, descriptor);
+ }
+ (*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();
+}
+} // 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 {
+ printer->Print(variables_,
+ "private boolean has$capitalized_name$;\n"
+ "private $type$ $name$_ = $default$;\n"
+ "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n");
+ if (IsStringUtf8Handling(descriptor_, params_)) {
+ printer->Print(variables_,
+ "public String get$capitalized_name$() { return $name$_.getString(); }\n"
+ "public $type$ get$capitalized_name$StringUtf8() { return $name$_; }\n"
+ "public $message_name$ set$capitalized_name$(String value) {\n"
+ " has$capitalized_name$ = true;\n"
+ " if ($name$_ == $default$) {\n"
+ " $name$_ = new $type$(value);\n"
+ " } else {\n"
+ " $name$_.setString(value);\n"
+ " }\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " has$capitalized_name$ = false;\n"
+ " $name$_ = $default$;\n"
+ " return this;\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "public $type$ get$capitalized_name$() { return $name$_; }\n");
+ if (IsVariableLenType(GetJavaType(descriptor_))) {
+ printer->Print(variables_,
+ "public $message_name$ set$capitalized_name$($type$ value) {\n"
+ " has$capitalized_name$ = true;\n"
+ " $name$_ = value;\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " has$capitalized_name$ = false;\n"
+ " $name$_ = $default$;\n"
+ " return this;\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "public $message_name$ set$capitalized_name$($type$ value) {\n"
+ " has$capitalized_name$ = true;\n"
+ " $name$_ = value;\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " has$capitalized_name$ = false;\n"
+ " $name$_ = $default$;\n"
+ " return this;\n"
+ "}\n");
+ }
+ }
+}
+
+void PrimitiveFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (other.has$capitalized_name$()) {\n"
+ " set$capitalized_name$(other.get$capitalized_name$());\n"
+ "}\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "set$capitalized_name$(input.read$capitalized_type$());\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (IsStringUtf8Handling(descriptor_, params_)) {
+ printer->Print(variables_,
+ "if (has$capitalized_name$()) {\n"
+ " output.writeStringUtf8($number$, get$capitalized_name$StringUtf8());\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "if (has$capitalized_name$()) {\n"
+ " output.write$capitalized_type$($number$, get$capitalized_name$());\n"
+ "}\n");
+ }
+}
+
+void PrimitiveFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ if (IsStringUtf8Handling(descriptor_, params_)) {
+ printer->Print(variables_,
+ "if (has$capitalized_name$()) {\n"
+ " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
+ " .computeStringUtf8Size($number$, get$capitalized_name$StringUtf8());\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "if (has$capitalized_name$()) {\n"
+ " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
+ " .compute$capitalized_type$Size($number$, get$capitalized_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_);
+ if (descriptor_->options().packed()) {
+ GOOGLE_LOG(FATAL) << "MicroRuntime does not support packed";
+ }
+}
+
+RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+ if (IsStringUtf8Handling(descriptor_, params_)) {
+ if (params_.java_use_vector()) {
+ printer->Print(variables_,
+ "private java.util.Vector $name$_ = new java.util.Vector();\n"
+ "public java.util.Vector get$capitalized_name$List() {\n"
+ " return $name$_;\n"
+ "}\n"
+ "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
+ "public String get$capitalized_name$(int index) {\n"
+ " return (($type$)$name$_.elementAt(index)).getString();\n"
+ "}\n"
+ "public $type$ get$capitalized_name$StringUtf8(int index) {\n"
+ " return ($type$)$name$_.elementAt(index);\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$(int index, String value) {\n"
+ "$null_check$"
+ " $name$_.setElementAt(new $type$(value), index);\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ add$capitalized_name$(String value) {\n"
+ "$null_check$"
+ " $name$_.addElement(new $type$(value));\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " $name$_.removeAllElements();\n"
+ " return this;\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "private java.util.List<$type$> $name$_ =\n"
+ " java.util.Collections.emptyList();\n"
+ "public java.util.List<$type$> get$capitalized_name$List() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n"
+ "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
+ "public String get$capitalized_name$(int index) {\n"
+ " return $name$_.get(index).getString();\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$(int index, String value) {\n"
+ "$null_check$"
+ " $name$_.set(index, new $type$(value));\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ add$capitalized_name$(String value) {\n"
+ "$null_check$"
+ " if ($name$_.isEmpty()) {\n"
+ " $name$_ = new java.util.ArrayList<$type$>();\n"
+ " }\n"
+ " $name$_.add(new $type$(value));\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " $name$_ = java.util.Collections.emptyList();\n"
+ " return this;\n"
+ "}\n");
+ }
+ } else if (params_.java_use_vector()) {
+ if (IsReferenceType(GetJavaType(descriptor_))) {
+ printer->Print(variables_,
+ "private java.util.Vector $name$_ = new java.util.Vector();\n"
+ "public java.util.Vector get$capitalized_name$List() {\n"
+ " return $name$_;\n"
+ "}\n"
+ "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
+ "public $type$ get$capitalized_name$(int index) {\n"
+ " return ($type$) $name$_.elementAt(index);\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
+ "$null_check$"
+ " $name$_.setElementAt(value, index);\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ add$capitalized_name$($type$ value) {\n"
+ "$null_check$"
+ " $name$_.addElement(value);\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " $name$_.removeAllElements();\n"
+ " return this;\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "private java.util.Vector $name$_ = new java.util.Vector();\n"
+ "public java.util.Vector get$capitalized_name$List() {\n"
+ " return $name$_;\n"
+ "}\n"
+ "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
+ "public $type$ get$capitalized_name$(int index) {\n"
+ " return (($boxed_type$)$name$_.elementAt(index)).$type$Value();\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
+ "$null_check$"
+ " $name$_.setElementAt(new $boxed_type$(value), index);\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ add$capitalized_name$($type$ value) {\n"
+ "$null_check$"
+ " $name$_.addElement(new $boxed_type$(value));\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " $name$_.removeAllElements();\n"
+ " return this;\n"
+ "}\n");
+ }
+ } else {
+ printer->Print(variables_,
+ "private java.util.List<$boxed_type$> $name$_ =\n"
+ " java.util.Collections.emptyList();\n"
+ "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n"
+ "public int get$capitalized_name$Count() { return $name$_.size(); }\n"
+ "public $type$ get$capitalized_name$(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$(int index, $type$ value) {\n"
+ "$null_check$"
+ " $name$_.set(index, value);\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ add$capitalized_name$($type$ value) {\n"
+ "$null_check$"
+ " if ($name$_.isEmpty()) {\n"
+ " $name$_ = new java.util.ArrayList<$boxed_type$>();\n"
+ " }\n"
+ " $name$_.add(value);\n"
+ " return this;\n"
+ "}\n"
+ "public $message_name$ clear$capitalized_name$() {\n"
+ " $name$_ = java.util.Collections.emptyList();\n"
+ " return this;\n"
+ "}\n");
+ }
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "private int $name$MemoizedSerializedSize;\n");
+ }
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ if (params_.java_use_vector()) {
+ printer->Print(variables_,
+ "if (other.$name$_.size() != 0) {\n"
+ " for (int i = 0; i < other.$name$_.size(); i++)) {\n"
+ " result.$name$_.addElement(other.$name$_.elementAt(i));\n"
+ " }\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "if (!other.$name$_.isEmpty()) {\n"
+ " if (result.$name$_.isEmpty()) {\n"
+ " result.$name$_ = new java.util.ArrayList<$type$>();\n"
+ " }\n"
+ " result.$name$_.addAll(other.$name$_);\n"
+ "}\n");
+ }
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int limit = input.pushLimit(length);\n"
+ "while (input.getBytesUntilLimit() > 0) {\n"
+ " add$capitalized_name$(input.read$capitalized_type$());\n"
+ "}\n"
+ "input.popLimit(limit);\n");
+ } else {
+ printer->Print(variables_,
+ "add$capitalized_name$(input.read$capitalized_type$());\n");
+ }
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (get$capitalized_name$List().size() > 0) {\n"
+ " output.writeRawVarint32($tag$);\n"
+ " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+ "}\n");
+ if (params_.java_use_vector()) {
+ printer->Print(variables_,
+ "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
+ " output.write$capitalized_type$NoTag(get$capitalized_name$(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for ($type$ element : get$capitalized_name$List()) {\n"
+ " output.write$capitalized_type$NoTag(element);\n"
+ "}\n");
+ }
+ } else {
+ if (params_.java_use_vector()) {
+ if (IsStringUtf8Handling(descriptor_, params_)) {
+ printer->Print(variables_,
+ "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
+ " output.writeStringUtf8($number$, get$capitalized_name$StringUtf8(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
+ " output.write$capitalized_type$($number$, get$capitalized_name$(i));\n"
+ "}\n");
+ }
+ } else {
+ if (IsStringUtf8Handling(descriptor_, params_)) {
+ printer->Print(variables_,
+ "for ($type$ element : get$capitalized_name$List()) {\n"
+ " output.writeStringUtf8($number$, element);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for ($type$ element : get$capitalized_name$List()) {\n"
+ " output.write$capitalized_type$($number$, element);\n"
+ "}\n");
+ }
+ }
+ }
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "{\n"
+ " int dataSize = 0;\n");
+ printer->Indent();
+
+ if (FixedSize(descriptor_->type()) == -1) {
+ if (params_.java_use_vector()) {
+ printer->Print(variables_,
+ "for (int i = 0; i < get$capitalized_name$List().size(); i++) {\n"
+ " dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n");
+ if (IsStringUtf8Handling(descriptor_, params_)) {
+ printer->Print(variables_,
+ " .computeStringUtf8SizeNoTag(get$capitalized_name$StringUtf8(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ " .compute$capitalized_type$SizeNoTag(($type$)get$capitalized_name$(i));\n"
+ "}\n");
+ }
+ } else {
+ printer->Print(variables_,
+ "for ($type$ element : get$capitalized_name$List()) {\n"
+ " dataSize += com.google.protobuf.micro.CodedOutputStreamMicro\n");
+ if (IsStringUtf8Handling(descriptor_, params_)) {
+ printer->Print(variables_,
+ " .computeStringUtf8SizeNoTag(element);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ " .compute$capitalized_type$SizeNoTag(element);\n"
+ "}\n");
+ }
+ }
+ } else {
+ printer->Print(variables_,
+ "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
+ }
+
+ printer->Print(
+ "size += dataSize;\n");
+
+ if (descriptor_->options().packed()) {
+ if (params_.java_use_vector()) {
+ printer->Print(variables_,
+ "if (get$capitalized_name$List().size() != 0) {\n");
+ } else {
+ printer->Print(variables_,
+ "if (!get$capitalized_name$List().isEmpty()) {\n");
+ }
+ printer->Print(variables_,
+ " size += $tag_size$;\n"
+ " size += com.google.protobuf.micro.CodedOutputStreamMicro\n"
+ " .computeInt32SizeNoTag(dataSize);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "size += $tag_size$ * get$capitalized_name$List().size();\n");
+ }
+
+ // cache the data size for packed fields.
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "$name$MemoizedSerializedSize = dataSize;\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+string RepeatedPrimitiveFieldGenerator::GetBoxedType() const {
+ return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+} // namespace javamicro
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javamicro/javamicro_primitive_field.h b/src/google/protobuf/compiler/javamicro/javamicro_primitive_field.h
new file mode 100644
index 0000000..88d8eec
--- /dev/null
+++ b/src/google/protobuf/compiler/javamicro/javamicro_primitive_field.h
@@ -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_JAVAMICRO_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVAMICRO_PRIMITIVE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/javamicro/javamicro_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javamicro {
+
+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 javamicro
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVAMICRO_PRIMITIVE_FIELD_H__
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index 0a2c0b2..41dc5b9 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/compiler/cpp/cpp_generator.h>
#include <google/protobuf/compiler/python/python_generator.h>
#include <google/protobuf/compiler/java/java_generator.h>
+#include <google/protobuf/compiler/javamicro/javamicro_generator.h>
int main(int argc, char* argv[]) {
@@ -56,5 +57,10 @@ int main(int argc, char* argv[]) {
cli.RegisterGenerator("--python_out", &py_generator,
"Generate Python source file.");
+ // Proto2 JavaMicro
+ google::protobuf::compiler::javamicro::JavaMicroGenerator javamicro_generator;
+ cli.RegisterGenerator("--javamicro_out", &javamicro_generator,
+ "Generate Java source file micro runtime.");
+
return cli.Run(argc, argv);
}
diff --git a/src/google/protobuf/unittest_import_micro.proto b/src/google/protobuf/unittest_import_micro.proto
new file mode 100644
index 0000000..adac807
--- /dev/null
+++ b/src/google/protobuf/unittest_import_micro.proto
@@ -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 = MICRO_RUNTIME.
+
+package protobuf_unittest_import;
+
+// java_package and java_outer_classname are specified on the command line.
+//option java_package = "com.google.protobuf.micro";
+//option java_outer_classname = "UnittestImportMicro";
+
+message ImportMessageMicro {
+ optional int32 d = 1;
+}
+
+enum ImportEnumMicro {
+ IMPORT_MICRO_FOO = 7;
+ IMPORT_MICRO_BAR = 8;
+ IMPORT_MICRO_BAZ = 9;
+}
diff --git a/src/google/protobuf/unittest_micro.proto b/src/google/protobuf/unittest_micro.proto
new file mode 100644
index 0000000..3d7fcd2
--- /dev/null
+++ b/src/google/protobuf/unittest_micro.proto
@@ -0,0 +1,162 @@
+// 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_micro.proto";
+
+option java_package = "com.google.protobuf.micro";
+option java_outer_classname = "MicroOuterClass";
+
+// Same as TestAllTypes but with the micro runtime.
+message TestAllTypesMicro {
+
+ 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 ForeignMessageMicro optional_foreign_message = 19;
+ optional protobuf_unittest_import.ImportMessageMicro
+ optional_import_message = 20;
+
+ optional NestedEnum optional_nested_enum = 21;
+ optional ForeignEnumMicro optional_foreign_enum = 22;
+ optional protobuf_unittest_import.ImportEnumMicro 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 ForeignMessageMicro repeated_foreign_message = 49;
+ repeated protobuf_unittest_import.ImportMessageMicro
+ repeated_import_message = 50;
+
+ repeated NestedEnum repeated_nested_enum = 51;
+ repeated ForeignEnumMicro repeated_foreign_enum = 52;
+ repeated protobuf_unittest_import.ImportEnumMicro repeated_import_enum = 53;
+
+ repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+ repeated string repeated_cord = 55 [ctype=CORD];
+
+ // 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 NestedEnum default_nested_enum = 81 [default = BAR];
+ optional ForeignEnumMicro default_foreign_enum = 82
+ [default = FOREIGN_MICRO_BAR];
+ optional protobuf_unittest_import.ImportEnumMicro
+ default_import_enum = 83 [default = IMPORT_MICRO_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 ForeignMessageMicro {
+ optional int32 c = 1;
+}
+
+enum ForeignEnumMicro {
+ FOREIGN_MICRO_FOO = 4;
+ FOREIGN_MICRO_BAR = 5;
+ FOREIGN_MICRO_BAZ = 6;
+}
+
+// Test that deprecated fields work. We only verify that they compile (at one
+// point this failed).
+message TestDeprecatedMicro {
+ optional int32 deprecated_field = 1 [deprecated = true];
+}
diff --git a/src/google/protobuf/unittest_recursive_micro.proto b/src/google/protobuf/unittest_recursive_micro.proto
new file mode 100644
index 0000000..a256852
--- /dev/null
+++ b/src/google/protobuf/unittest_recursive_micro.proto
@@ -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.micro";
+
+message RecursiveMessageMicro {
+ message NestedMessage {
+ optional RecursiveMessageMicro a = 1;
+ }
+
+ required int32 id = 1;
+ optional NestedMessage nested_message = 2;
+ optional RecursiveMessageMicro optional_recursive_message_micro = 3;
+ repeated RecursiveMessageMicro repeated_recursive_message_micro = 4;
+}
diff --git a/src/google/protobuf/unittest_simple_micro.proto b/src/google/protobuf/unittest_simple_micro.proto
new file mode 100644
index 0000000..057bf3d
--- /dev/null
+++ b/src/google/protobuf/unittest_simple_micro.proto
@@ -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.micro";
+
+message SimpleMessageMicro {
+ 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];
+}
diff --git a/src/google/protobuf/unittest_stringutf8_micro.proto b/src/google/protobuf/unittest_stringutf8_micro.proto
new file mode 100644
index 0000000..e4bbe3d
--- /dev/null
+++ b/src/google/protobuf/unittest_stringutf8_micro.proto
@@ -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.micro";
+
+message StringUtf8 {
+ optional string id = 1;
+ repeated string rs = 2;
+}