Add a flag to use offset/length with byte arrays. am: 4d68239ebc am: dbe8383ccc -s ours Change-Id: Iaef4210e3d46615c4d03baec3577bea502a5fc6f
diff --git a/Android.bp b/Android.bp index 237d66c..b61e101 100644 --- a/Android.bp +++ b/Android.bp
@@ -225,6 +225,26 @@ }, } +// Compiler library for the host +// ======================================================= +cc_library_host_shared { + name: "libprotoc", + defaults: ["libprotobuf-cpp-lite-defaults"], + + srcs: protobuf_cc_full_src_files + [ + "src/google/protobuf/compiler/plugin.pb.cc", + ], + + local_include_dirs: [ + "config", + ], + export_include_dirs: ["src", "config"], + + rtti: true, + + shared_libs: ["libz-host"], +} + // Android Protocol buffer compiler, aprotoc (host executable) // used by the build systems as $(PROTOC) defined in // build/core/config.mk
diff --git a/config/config.h b/config/config.h new file mode 100644 index 0000000..366aa84 --- /dev/null +++ b/config/config.h
@@ -0,0 +1,153 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* the name of <hash_map> */ +#define HASH_MAP_CLASS unordered_map + +/* the location of <unordered_map> or <hash_map> */ +#define HASH_MAP_H <tr1/unordered_map> + +/* the namespace of hash_map/hash_set */ +#define HASH_NAMESPACE std::tr1 + +/* the name of <hash_set> */ +#define HASH_SET_CLASS unordered_set + +/* the location of <unordered_set> or <hash_set> */ +#define HASH_SET_H <tr1/unordered_set> + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* define if the compiler has hash_map */ +#define HAVE_HASH_MAP 1 + +/* define if the compiler has hash_set */ +#define HAVE_HASH_SET 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the <limits.h> header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the `mkdir' function. */ +#define HAVE_MKDIR 1 + +/* Define if you have POSIX threads libraries and header files. */ +#define HAVE_PTHREAD 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strtol' function. */ +#define HAVE_STRTOL 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Enable classes using zlib compression. */ +#define HAVE_ZLIB 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Name of package */ +#define PACKAGE "protobuf" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "protobuf@googlegroups.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "Protocol Buffers" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "Protocol Buffers 2.6.1" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "protobuf" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "2.6.1" + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef PTHREAD_CREATE_JOINABLE */ + +/* 64bit enabled */ +/* #undef SOLARIS_64BIT_ENABLED */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif + + +/* Version number of package */ +#define VERSION "2.6.1" + +/* Define to 1 if on MINIX. */ +/* #undef _MINIX */ + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +/* #undef _POSIX_1_SOURCE */ + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +/* #undef _POSIX_SOURCE */
diff --git a/javanano/pom.xml b/javanano/pom.xml index 1af4249..309b6c3 100644 --- a/javanano/pom.xml +++ b/javanano/pom.xml
@@ -109,6 +109,11 @@ <arg value="src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto" /> </exec> <exec executable="../src/protoc"> + <arg value="--javanano_out=store_unknown_fields=true:target/generated-test-sources" /> + <arg value="--proto_path=src/test/java/com" /> + <arg value="src/test/java/com/google/protobuf/unittest_unknown_enum_values_nano.proto" /> + </exec> + <exec executable="../src/protoc"> <arg value="--javanano_out=java_nano_generate_has=true,generate_equals=true,generate_clone=true:target/generated-test-sources" /> <arg value="--proto_path=src/test/java/com" /> <arg value="src/test/java/com/google/protobuf/nano/unittest_has_nano.proto" />
diff --git a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java index 1a17134..44544f4 100644 --- a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java +++ b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java
@@ -42,6 +42,8 @@ import com.google.protobuf.nano.NanoReferenceTypesCompat; import com.google.protobuf.nano.UnittestSimpleNano.SimpleMessageNano; import com.google.protobuf.nano.UnittestSingleNano.SingleMessageNano; +import com.google.protobuf.nano.UnknownEnumValuesNanoOuterClass.StandardVersion; +import com.google.protobuf.nano.UnknownEnumValuesNanoOuterClass.VersionWithoutVal3; import com.google.protobuf.nano.testext.nano.Extensions; import com.google.protobuf.nano.testext.nano.Extensions.AnotherMessage; import com.google.protobuf.nano.testext.nano.Extensions.MessageWithGroup; @@ -4468,6 +4470,67 @@ assertTrue("bar was not deserialized correctly", Arrays.equals(new byte[] { 7 }, bar)); } + public void testUnknownOptionalEnumValue() throws Exception { + StandardVersion standardMsg = new StandardVersion(); + standardMsg.optionalField = StandardVersion.VAL_3; + byte[] standardMsgBytes = MessageNano.toByteArray(standardMsg); + + // When parsing and reading, the unknown value appears as UNKNOWN. + VersionWithoutVal3 withoutVal3Msg = new VersionWithoutVal3(); + MessageNano.mergeFrom(withoutVal3Msg, standardMsgBytes); + assertEquals(VersionWithoutVal3.UNKNOWN, withoutVal3Msg.optionalField); + + // When serializing and reparsing as the standard version, the old, unknown value wins out (even + // if a new one is set). + withoutVal3Msg.optionalField = VersionWithoutVal3.VAL_2; + byte[] withoutVal3MsgBytes = MessageNano.toByteArray(withoutVal3Msg); + StandardVersion standardMsgFromWithoutVal3Msg = new StandardVersion(); + MessageNano.mergeFrom(standardMsgFromWithoutVal3Msg, withoutVal3MsgBytes); + assertEquals(StandardVersion.VAL_3, standardMsgFromWithoutVal3Msg.optionalField); + } + + public void testUnknownRepeatedEnumValue() throws Exception { + StandardVersion standardMsg = new StandardVersion(); + standardMsg.repeatedField = new int[] { StandardVersion.VAL_3, StandardVersion.VAL_2 }; + byte[] standardMsgBytes = MessageNano.toByteArray(standardMsg); + + // When parsing and reading, the unknown value is stripped out. + VersionWithoutVal3 withoutVal3Msg = new VersionWithoutVal3(); + MessageNano.mergeFrom(withoutVal3Msg, standardMsgBytes); + assertTrue(Arrays.equals(new int[] { VersionWithoutVal3.VAL_2 }, withoutVal3Msg.repeatedField)); + + // When serializing and reparsing as the standard version, the old, unknown value reappears, but + // at the end of all entries (including any newly added ones). + withoutVal3Msg.repeatedField = new int[] { VersionWithoutVal3.VAL_2, VersionWithoutVal3.VAL_1 }; + byte[] withoutVal3MsgBytes = MessageNano.toByteArray(withoutVal3Msg); + StandardVersion standardMsgFromWithoutVal3Msg = new StandardVersion(); + MessageNano.mergeFrom(standardMsgFromWithoutVal3Msg, withoutVal3MsgBytes); + assertTrue(Arrays.equals( + new int[] { StandardVersion.VAL_2, StandardVersion.VAL_1, StandardVersion.VAL_3 }, + standardMsgFromWithoutVal3Msg.repeatedField)); + } + + public void testUnknownRepeatedPackedEnumValue() throws Exception { + StandardVersion standardMsg = new StandardVersion(); + standardMsg.packedField = new int[] { StandardVersion.VAL_3, StandardVersion.VAL_2 }; + byte[] standardMsgBytes = MessageNano.toByteArray(standardMsg); + + // When parsing and reading, the unknown value is stripped out. + VersionWithoutVal3 withoutVal3Msg = new VersionWithoutVal3(); + MessageNano.mergeFrom(withoutVal3Msg, standardMsgBytes); + assertTrue(Arrays.equals(new int[] { VersionWithoutVal3.VAL_2 }, withoutVal3Msg.packedField)); + + // When serializing and reparsing as the standard version, the old, unknown value reappears, but + // at the end of all entries (including any newly added ones). + withoutVal3Msg.packedField = new int[] { VersionWithoutVal3.VAL_2, VersionWithoutVal3.VAL_1 }; + byte[] withoutVal3MsgBytes = MessageNano.toByteArray(withoutVal3Msg); + StandardVersion standardMsgFromWithoutVal3Msg = new StandardVersion(); + MessageNano.mergeFrom(standardMsgFromWithoutVal3Msg, withoutVal3MsgBytes); + assertTrue(Arrays.equals( + new int[] { StandardVersion.VAL_2, StandardVersion.VAL_1, StandardVersion.VAL_3 }, + standardMsgFromWithoutVal3Msg.packedField)); + } + private void assertHasWireData(MessageNano message, boolean expected) { byte[] bytes = MessageNano.toByteArray(message); int wireLength = bytes.length;
diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_unknown_enum_values.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_unknown_enum_values.proto new file mode 100644 index 0000000..59d91c4 --- /dev/null +++ b/javanano/src/test/java/com/google/protobuf/nano/unittest_unknown_enum_values.proto
@@ -0,0 +1,58 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2016 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 protobuf_unittest; + +option java_package = "com.google.protobuf.nano"; +option java_outer_classname = "UnknownEnumValuesNanoOuterClass"; + +message StandardVersion { + enum Enum { + UNKNOWN = 0; + VAL_1 = 1; + VAL_2 = 2; + VAL_3 = 3; + } + optional Enum optional_field = 1; + repeated Enum repeated_field = 2; + repeated Enum packed_field = 3 [packed = true]; +} + +message VersionWithoutVal3 { + enum Enum { + UNKNOWN = 0; + VAL_1 = 1; + VAL_2 = 2; + // VAL_3 is unknown in this version. + } + optional Enum optional_field = 1; + repeated Enum repeated_field = 2; + repeated Enum packed_field = 3 [packed = true]; +}
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc index 7666db3..39a4eeb 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
@@ -144,6 +144,9 @@ void EnumFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { + if (params_.store_unknown_fields()) { + printer->Print("int initialPos = input.getPosition();\n"); + } printer->Print(variables_, "int value = input.readInt32();\n" "switch (value) {\n"); @@ -155,11 +158,20 @@ " has$capitalized_name$ = true;\n"); } printer->Print( - " break;\n" - "}\n"); - // No default case: in case of invalid value from the wire, preserve old - // field value. Also we are not storing the invalid value into the unknown - // fields, because there is no way to get the value out. + " break;\n"); + if (params_.store_unknown_fields()) { + // If storing unknown fields, store invalid values there. + // This is consistent with full protobuf, but note that if a client writes + // a new value to this field, both will be serialized on the wire, and + // other clients which are aware of unknown fields will see the previous + // value, not the new one. + printer->Print( + " default:\n" + " input.rewindToPosition(initialPos);\n" + " storeUnknownField(input, tag);\n" + " break;\n"); + } + printer->Print("}\n"); } void EnumFieldGenerator:: @@ -300,6 +312,9 @@ void AccessorEnumFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { + if (params_.store_unknown_fields()) { + printer->Print("int initialPos = input.getPosition();\n"); + } printer->Print(variables_, "int value = input.readInt32();\n" "switch (value) {\n"); @@ -307,11 +322,20 @@ printer->Print(variables_, " $name$_ = value;\n" " $set_has$;\n" - " break;\n" - "}\n"); - // No default case: in case of invalid value from the wire, preserve old - // field value. Also we are not storing the invalid value into the unknown - // fields, because there is no way to get the value out. + " break;\n"); + if (params_.store_unknown_fields()) { + // If storing unknown fields, store invalid values there. + // This is consistent with full protobuf, but note that if a client writes + // a new value to this field, both will be serialized on the wire, and + // other clients which are aware of unknown fields will see the previous + // value, not the new one. + printer->Print( + " default:\n" + " input.rewindToPosition(initialPos);\n" + " storeUnknownField(input, tag);\n" + " break;\n"); + } + printer->Print("}\n"); } void AccessorEnumFieldGenerator:: @@ -381,7 +405,11 @@ "for (int i = 0; i < length; i++) {\n" " if (i != 0) { // tag for first value already consumed.\n" " input.readTag();\n" - " }\n" + " }\n"); + if (params_.store_unknown_fields()) { + printer->Print(" int initialPos = input.getPosition();\n"); + } + printer->Print( " int value = input.readInt32();\n" " switch (value) {\n"); printer->Indent(); @@ -389,7 +417,19 @@ printer->Outdent(); printer->Print(variables_, " validValues[validCount++] = value;\n" - " break;\n" + " break;\n"); + if (params_.store_unknown_fields()) { + // If storing unknown fields, store invalid values there. + // This is consistent with full protobuf. Note that this can lead to very + // strange behaviors if a value is serialized and reread, e.g. changes in + // value ordering. + printer->Print( + " default:\n" + " input.rewindToPosition(initialPos);\n" + " storeUnknownField(input, tag);\n" + " break;\n"); + } + printer->Print(variables_, " }\n" "}\n" "if (validCount != 0) {\n" @@ -432,7 +472,11 @@ " if (i != 0) {\n" " java.lang.System.arraycopy(this.$name$, 0, newArray, 0, i);\n" " }\n" - " while (input.getBytesUntilLimit() > 0) {\n" + " while (input.getBytesUntilLimit() > 0) {\n"); + if (params_.store_unknown_fields()) { + printer->Print(" int initialPos = input.getPosition();\n"); + } + printer->Print(variables_, " int value = input.readInt32();\n" " switch (value) {\n"); printer->Indent(); @@ -442,7 +486,19 @@ printer->Outdent(); printer->Print(variables_, " newArray[i++] = value;\n" - " break;\n" + " break;\n"); + if (params_.store_unknown_fields()) { + // If storing unknown fields, store invalid values there. + // This is consistent with full protobuf. Note that this can lead to very + // strange behaviors if a value is serialized and reread, e.g. changes in + // value ordering. + printer->Print(variables_, + " default:\n" + " input.rewindToPosition(initialPos);\n" + " storeUnknownField(input, $non_packed_tag$);\n" + " break;\n"); + } + printer->Print(variables_, " }\n" " }\n" " this.$name$ = newArray;\n"