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"