소스 검색

Merge branch 'master' into down-integrate-with-msvc-fix

Adam Cozzette 9 년 전
부모
커밋
5d63097fc2
82개의 변경된 파일1668개의 추가작업 그리고 759개의 파일을 삭제
  1. 4 4
      BUILD
  2. 2 1
      Makefile.am
  3. 1 1
      cmake/extract_includes.bat.in
  4. 1 2
      composer.json
  5. 4 4
      conformance/failure_list_csharp.txt
  6. 6 6
      csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
  7. 1 1
      csharp/src/Google.Protobuf.Test/project.json
  8. 1 1
      csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
  9. 11 73
      csharp/src/Google.Protobuf/JsonFormatter.cs
  10. 1 1
      csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
  11. 5 5
      csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs
  12. 1 0
      docs/third_party.md
  13. 1 1
      java/compatibility_tests/v2.5.0/protos/pom.xml
  14. 28 5
      java/core/pom.xml
  15. 45 5
      java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java
  16. 1 1
      java/core/src/main/java/com/google/protobuf/MapFieldLite.java
  17. 30 2
      java/lite/pom.xml
  18. 1 1
      java/pom.xml
  19. 17 5
      java/util/pom.xml
  20. 2 2
      javanano/src/main/java/com/google/protobuf/nano/InternalNano.java
  21. 1 1
      javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java
  22. 1 1
      jenkins/buildcmds/pull_request_32.sh
  23. 1 0
      jenkins/docker/Dockerfile
  24. 4 1
      jenkins/docker32/Dockerfile
  25. 25 12
      js/binary/decoder.js
  26. 23 0
      js/binary/decoder_test.js
  27. 23 6
      js/binary/encoder.js
  28. 1 1
      js/package.json
  29. 21 0
      objectivec/GPBCodedInputStream.h
  30. 8 0
      objectivec/GPBCodedInputStream.m
  31. 10 1
      objectivec/GPBMessage.h
  32. 1 1
      objectivec/README.md
  33. 125 2
      php/ext/google/protobuf/array.c
  34. 34 21
      php/ext/google/protobuf/def.c
  35. 2 2
      php/ext/google/protobuf/message.c
  36. 1 0
      php/ext/google/protobuf/protobuf.c
  37. 19 0
      php/ext/google/protobuf/protobuf.h
  38. 22 2
      php/ext/google/protobuf/storage.c
  39. 130 9
      php/ext/google/protobuf/type_check.c
  40. 38 3
      php/src/Google/Protobuf/Internal/GPBUtil.php
  41. 23 24
      php/src/Google/Protobuf/Internal/GPBWire.php
  42. 58 8
      php/src/Google/Protobuf/Internal/InputStream.php
  43. 10 5
      php/src/Google/Protobuf/Internal/Message.php
  44. 36 15
      php/src/Google/Protobuf/Internal/OutputStream.php
  45. 0 175
      php/src/Google/Protobuf/Internal/Type.php
  46. 21 4
      php/src/Google/Protobuf/descriptor.php
  47. 87 35
      php/tests/array_test.php
  48. 64 10
      php/tests/generated_class_test.php
  49. 28 0
      php/tests/google/protobuf/empty.pb.php
  50. 44 12
      php/tests/map_field_test.php
  51. 93 55
      php/tests/php_implementation_test.php
  52. 3 2
      php/tests/test.sh
  53. 26 12
      php/tests/test_base.php
  54. 34 0
      php/tests/test_no_namespace.pb.php
  55. 5 0
      php/tests/test_no_namespace.proto
  56. 83 38
      php/tests/test_util.php
  57. 13 0
      php/tests/well_known_test.php
  58. 1 0
      phpunit.xml
  59. 17 7
      protobuf.bzl
  60. 1 1
      python/README.md
  61. 4 0
      python/google/protobuf/pyext/message.cc
  62. 44 0
      ruby/ext/google/protobuf_c/message.c
  63. 10 0
      ruby/tests/basic.rb
  64. 2 0
      ruby/travis-test.sh
  65. 112 112
      src/Makefile.am
  66. 1 0
      src/google/protobuf/arena.h
  67. 38 9
      src/google/protobuf/compiler/command_line_interface.cc
  68. 17 8
      src/google/protobuf/compiler/command_line_interface.h
  69. 38 0
      src/google/protobuf/compiler/command_line_interface_unittest.cc
  70. 4 4
      src/google/protobuf/compiler/mock_code_generator.cc
  71. 16 2
      src/google/protobuf/compiler/php/php_generator.cc
  72. 1 2
      src/google/protobuf/repeated_field.h
  73. 9 1
      src/google/protobuf/stubs/atomicops.h
  74. 3 3
      src/google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h
  75. 5 5
      src/google/protobuf/stubs/atomicops_internals_generic_gcc.h
  76. 2 2
      src/google/protobuf/stubs/platform_macros.h
  77. 1 9
      src/google/protobuf/stubs/type_traits.h
  78. 4 4
      src/google/protobuf/util/internal/constants.h
  79. 6 2
      src/google/protobuf/util/internal/protostream_objectsource.cc
  80. 6 2
      src/google/protobuf/util/internal/protostream_objectwriter.cc
  81. 15 6
      src/google/protobuf/util/internal/utility.cc
  82. 30 1
      tests.sh

+ 4 - 4
BUILD

@@ -577,7 +577,7 @@ py_library(
 )
 
 cc_binary(
-    name = "internal/_api_implementation.so",
+    name = "python/google/protobuf/internal/_api_implementation.so",
     srcs = ["python/google/protobuf/internal/api_implementation.cc"],
     copts = COPTS + [
         "-DPYTHON_PROTO2_CPP_IMPL_V2",
@@ -591,7 +591,7 @@ cc_binary(
 )
 
 cc_binary(
-    name = "pyext/_message.so",
+    name = "python/google/protobuf/pyext/_message.so",
     srcs = glob([
         "python/google/protobuf/pyext/*.cc",
         "python/google/protobuf/pyext/*.h",
@@ -653,8 +653,8 @@ py_proto_library(
     data = select({
         "//conditions:default": [],
         ":use_fast_cpp_protos": [
-            ":internal/_api_implementation.so",
-            ":pyext/_message.so",
+            ":python/google/protobuf/internal/_api_implementation.so",
+            ":python/google/protobuf/pyext/_message.so",
         ],
     }),
     default_runtime = "",

+ 2 - 1
Makefile.am

@@ -577,7 +577,6 @@ php_EXTRA_DIST=                                              \
   php/src/Google/Protobuf/Internal/DescriptorPool.php        \
   php/src/Google/Protobuf/Internal/OneofField.php            \
   php/src/Google/Protobuf/Internal/MapEntry.php              \
-  php/src/Google/Protobuf/Internal/Type.php                  \
   php/src/Google/Protobuf/Internal/InputStream.php           \
   php/src/Google/Protobuf/Internal/OutputStream.php          \
   php/src/Google/Protobuf/Internal/MessageBuilderContext.php \
@@ -600,6 +599,8 @@ php_EXTRA_DIST=                                              \
   php/tests/test_include.pb.php                              \
   php/tests/map_field_test.php                               \
   php/tests/test_base.php                                    \
+  php/tests/test_no_namespace.proto                          \
+  php/tests/test_no_namespace.pb.php                         \
   php/tests/test_util.php                                    \
   php/tests/test.proto                                       \
   php/tests/test.pb.php                                      \

+ 1 - 1
cmake/extract_includes.bat.in

@@ -80,10 +80,10 @@ copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_intern
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm_gcc.h include\google\protobuf\stubs\atomicops_internals_arm_gcc.h
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm_qnx.h include\google\protobuf\stubs\atomicops_internals_arm_qnx.h
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_atomicword_compat.h include\google\protobuf\stubs\atomicops_internals_atomicword_compat.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_generic_c11_atomic.h include\google\protobuf\stubs\atomicops_internals_generic_c11_atomic.h
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_generic_gcc.h include\google\protobuf\stubs\atomicops_internals_generic_gcc.h
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_macosx.h include\google\protobuf\stubs\atomicops_internals_macosx.h
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_mips_gcc.h include\google\protobuf\stubs\atomicops_internals_mips_gcc.h
-copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_pnacl.h include\google\protobuf\stubs\atomicops_internals_pnacl.h
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_power.h include\google\protobuf\stubs\atomicops_internals_power.h
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_ppc_gcc.h include\google\protobuf\stubs\atomicops_internals_ppc_gcc.h
 copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_solaris.h include\google\protobuf\stubs\atomicops_internals_solaris.h

+ 1 - 2
composer.json

@@ -17,8 +17,7 @@
     },
     "files": [
       "php/src/Google/Protobuf/descriptor.php",
-      "php/src/Google/Protobuf/descriptor_internal.pb.php",
-      "php/src/Google/Protobuf/Internal/Type.php"
+      "php/src/Google/Protobuf/descriptor_internal.pb.php"
     ]
   }
 }

+ 4 - 4
conformance/failure_list_csharp.txt

@@ -1,6 +1,6 @@
 Recommended.JsonInput.FieldNameWithDoubleUnderscores.JsonOutput
+Recommended.JsonInput.FieldNameWithDoubleUnderscores.ProtobufOutput
+Recommended.JsonInput.FieldNameWithDoubleUnderscores.Validator
+Required.JsonInput.FieldNameInLowerCamelCase.Validator
 Required.JsonInput.FieldNameInSnakeCase.JsonOutput
-Required.JsonInput.FieldNameWithMixedCases.JsonOutput
-Required.JsonInput.FieldNameWithMixedCases.ProtobufOutput
-Required.JsonInput.FieldNameWithMixedCases.Validator
-Required.JsonInput.OriginalProtoFieldName.JsonOutput
+Required.JsonInput.FieldNameInSnakeCase.ProtobufOutput

+ 6 - 6
csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs

@@ -229,16 +229,16 @@ namespace Google.Protobuf
         [Test]
         [TestCase("foo_bar", "fooBar")]
         [TestCase("bananaBanana", "bananaBanana")]
-        [TestCase("BANANABanana", "bananaBanana")]
+        [TestCase("BANANABanana", "BANANABanana")]
         [TestCase("simple", "simple")]
-        [TestCase("ACTION_AND_ADVENTURE", "actionAndAdventure")]
+        [TestCase("ACTION_AND_ADVENTURE", "ACTIONANDADVENTURE")]
         [TestCase("action_and_adventure", "actionAndAdventure")]
         [TestCase("kFoo", "kFoo")]
-        [TestCase("HTTPServer", "httpServer")]
-        [TestCase("CLIENT", "client")]
-        public void ToCamelCase(string original, string expected)
+        [TestCase("HTTPServer", "HTTPServer")]
+        [TestCase("CLIENT", "CLIENT")]
+        public void ToJsonName(string original, string expected)
         {
-            Assert.AreEqual(expected, JsonFormatter.ToCamelCase(original));
+            Assert.AreEqual(expected, JsonFormatter.ToJsonName(original));
         }
 
         [Test]

+ 1 - 1
csharp/src/Google.Protobuf.Test/project.json

@@ -21,7 +21,7 @@
   "dependencies": {
     "Google.Protobuf": { "target": "project" },
     "NUnit": "3.4.0",
-    "dotnet-test-nunit": "3.4.0-alpha-2",
+    "dotnet-test-nunit": "3.4.0-alpha-2"
   },
 
   "testRunner": "nunit",

+ 1 - 1
csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs

@@ -61,7 +61,7 @@ namespace Google.Protobuf
         {
             return new InvalidProtocolBufferException(
                 "While parsing a protocol message, the input ended unexpectedly " +
-                "in the middle of a field.  This could mean either than the " +
+                "in the middle of a field.  This could mean either that the " +
                 "input has been truncated or that an embedded message " +
                 "misreported its own length.");
         }

+ 11 - 73
csharp/src/Google.Protobuf/JsonFormatter.cs

@@ -248,87 +248,25 @@ namespace Google.Protobuf
             return !first;
         }
 
-        /// <summary>
-        /// Camel-case converter with added strictness for field mask formatting.
-        /// </summary>
-        /// <exception cref="InvalidOperationException">The field mask is invalid for JSON representation</exception>
-        private static string ToCamelCaseForFieldMask(string input)
+        // Converted from java/core/src/main/java/com/google/protobuf/Descriptors.java
+        internal static string ToJsonName(string name)
         {
-            for (int i = 0; i < input.Length; i++)
+            StringBuilder result = new StringBuilder(name.Length);
+            bool isNextUpperCase = false;
+            foreach (char ch in name)
             {
-                char c = input[i];
-                if (c >= 'A' && c <= 'Z')
+                if (ch == '_')
                 {
-                    throw new InvalidOperationException($"Invalid field mask to be converted to JSON: {input}");
+                    isNextUpperCase = true;
                 }
-                if (c == '_' && i < input.Length - 1)
-                {
-                    char next = input[i + 1];
-                    if (next < 'a' || next > 'z')
-                    {
-                        throw new InvalidOperationException($"Invalid field mask to be converted to JSON: {input}");
-                    }
-                }
-            }
-            return ToCamelCase(input);
-        }
-
-        // Converted from src/google/protobuf/util/internal/utility.cc ToCamelCase
-        internal static string ToCamelCase(string input)
-        {
-            bool capitalizeNext = false;
-            bool wasCap = true;
-            bool isCap = false;
-            bool firstWord = true;
-            StringBuilder result = new StringBuilder(input.Length);
-
-            for (int i = 0; i < input.Length; i++, wasCap = isCap)
-            {
-                isCap = char.IsUpper(input[i]);
-                if (input[i] == '_')
+                else if (isNextUpperCase)
                 {
-                    capitalizeNext = true;
-                    if (result.Length != 0)
-                    {
-                        firstWord = false;
-                    }
-                    continue;
-                }
-                else if (firstWord)
-                {
-                    // Consider when the current character B is capitalized,
-                    // first word ends when:
-                    // 1) following a lowercase:   "...aB..."
-                    // 2) followed by a lowercase: "...ABc..."
-                    if (result.Length != 0 && isCap &&
-                        (!wasCap || (i + 1 < input.Length && char.IsLower(input[i + 1]))))
-                    {
-                        firstWord = false;
-                        result.Append(input[i]);
-                    }
-                    else
-                    {
-                        result.Append(char.ToLowerInvariant(input[i]));
-                        continue;
-                    }
-                }
-                else if (capitalizeNext)
-                {
-                    capitalizeNext = false;
-                    if (char.IsLower(input[i]))
-                    {
-                        result.Append(char.ToUpperInvariant(input[i]));
-                        continue;
-                    }
-                    else
-                    {
-                        result.Append(input[i]);
-                        continue;
-                    }
+                    result.Append(char.ToUpperInvariant(ch));
+                    isNextUpperCase = false;
                 }
                 else
                 {
-                    result.Append(char.ToLowerInvariant(input[i]));
+                    result.Append(ch);
                 }
             }
             return result.ToString();

+ 1 - 1
csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs

@@ -97,7 +97,7 @@ namespace Google.Protobuf.Reflection
             // We could trust the generated code and check whether the type of the property is
             // a MapField, but that feels a tad nasty.
             this.propertyName = propertyName;
-            JsonName =  Proto.JsonName == "" ? JsonFormatter.ToCamelCase(Proto.Name) : Proto.JsonName;
+            JsonName =  Proto.JsonName == "" ? JsonFormatter.ToJsonName(Proto.Name) : Proto.JsonName;
         }
     
 

+ 5 - 5
csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs

@@ -52,7 +52,7 @@ namespace Google.Protobuf.WellKnownTypes
         /// </remarks>
         /// <param name="paths">Paths in the field mask</param>
         /// <param name="diagnosticOnly">Determines the handling of non-normalized values</param>
-        /// <exception cref="InvalidOperationException">The represented duration is invalid, and <paramref name="diagnosticOnly"/> is <c>false</c>.</exception>
+        /// <exception cref="InvalidOperationException">The represented field mask is invalid, and <paramref name="diagnosticOnly"/> is <c>false</c>.</exception>
         internal static string ToJson(IList<string> paths, bool diagnosticOnly)
         {
             var firstInvalid = paths.FirstOrDefault(p => !ValidatePath(p));
@@ -60,10 +60,10 @@ namespace Google.Protobuf.WellKnownTypes
             {
                 var writer = new StringWriter();
 #if DOTNET35
-                var query = paths.Select(JsonFormatter.ToCamelCase);
+                var query = paths.Select(JsonFormatter.ToJsonName);
                 JsonFormatter.WriteString(writer, string.Join(",", query.ToArray()));
 #else
-                JsonFormatter.WriteString(writer, string.Join(",", paths.Select(JsonFormatter.ToCamelCase)));
+                JsonFormatter.WriteString(writer, string.Join(",", paths.Select(JsonFormatter.ToJsonName)));
 #endif
                 return writer.ToString();
             }
@@ -85,9 +85,9 @@ namespace Google.Protobuf.WellKnownTypes
         }
 
         /// <summary>
-        /// Camel-case converter with added strictness for field mask formatting.
+        /// Checks whether the given path is valid for a field mask.
         /// </summary>
-        /// <exception cref="InvalidOperationException">The field mask is invalid for JSON representation</exception>
+        /// <returns>true if the path is valid; false otherwise</returns>
         private static bool ValidatePath(string input)
         {
             for (int i = 0; i < input.Length; i++)

+ 1 - 0
docs/third_party.md

@@ -83,6 +83,7 @@ These are projects we know about implementing Protocol Buffers for other program
 * Scala: https://github.com/SandroGrzicic/ScalaBuff
 * Scala: http://trueaccord.github.io/ScalaPB/
 * Swift: https://github.com/alexeyxo/protobuf-swift
+* Swift: https://github.com/apple/swift-protobuf/
 * Vala: https://launchpad.net/protobuf-vala
 * Visual Basic: http://code.google.com/p/protobuf-net/
 

+ 1 - 1
java/compatibility_tests/v2.5.0/protos/pom.xml

@@ -28,7 +28,7 @@
     <plugins>
       <plugin>
         <artifactId>maven-compiler-plugin</artifactId>
-        <version>3.3</version>
+        <version>3.6.0</version>
         <configuration>
           <source>1.6</source>
           <target>1.6</target>

+ 28 - 5
java/core/pom.xml

@@ -92,11 +92,34 @@
 
       <!-- Add the generated sources to the build -->
       <plugin>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <configuration>
-          <generatedSourcesDirectory>${generated.sources.dir}</generatedSourcesDirectory>
-          <generatedTestSourcesDirectory>${generated.testsources.dir}</generatedTestSourcesDirectory>
-        </configuration>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-generated-sources</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${generated.sources.dir}</source>
+              </sources>
+            </configuration>
+          </execution>
+          <execution>
+            <id>add-generated-test-sources</id>
+            <phase>generate-test-sources</phase>
+            <goals>
+              <goal>add-test-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${generated.testsources.dir}</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
       </plugin>
 
       <!-- OSGI bundle configuration -->

+ 45 - 5
java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java

@@ -33,11 +33,12 @@ package com.google.protobuf;
 import static java.lang.Math.max;
 import static java.lang.Math.min;
 
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.lang.ref.SoftReference;
+import java.lang.reflect.Field;
 import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
 
 /**
  * Utility class to provide efficient writing of {@link ByteBuffer}s to {@link OutputStream}s.
@@ -74,6 +75,12 @@ final class ByteBufferWriter {
   private static final ThreadLocal<SoftReference<byte[]>> BUFFER =
       new ThreadLocal<SoftReference<byte[]>>();
 
+  /**
+   * This is a hack for GAE, where {@code FileOutputStream} is unavailable.
+   */
+  private static final Class<?> FILE_OUTPUT_STREAM_CLASS = safeGetClass("java.io.FileOutputStream");
+  private static final long CHANNEL_FIELD_OFFSET = getChannelFieldOffset(FILE_OUTPUT_STREAM_CLASS);
+
   /**
    * For testing purposes only. Clears the cached buffer to force a new allocation on the next
    * invocation.
@@ -93,10 +100,7 @@ final class ByteBufferWriter {
         // Optimized write for array-backed buffers.
         // Note that we're taking the risk that a malicious OutputStream could modify the array.
         output.write(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
-      } else if (output instanceof FileOutputStream) {
-        // Use a channel to write out the ByteBuffer. This will automatically empty the buffer.
-        ((FileOutputStream) output).getChannel().write(buffer);
-      } else {
+      } else if (!writeToChannel(buffer, output)){
         // Read all of the data from the buffer to an array.
         // TODO(nathanmittler): Consider performance improvements for other "known" stream types.
         final byte[] array = getOrCreateBuffer(buffer.remaining());
@@ -142,4 +146,40 @@ final class ByteBufferWriter {
   private static void setBuffer(byte[] value) {
     BUFFER.set(new SoftReference<byte[]>(value));
   }
+
+  private static boolean writeToChannel(ByteBuffer buffer, OutputStream output) throws IOException {
+    if (CHANNEL_FIELD_OFFSET >= 0 && FILE_OUTPUT_STREAM_CLASS.isInstance(output)) {
+      // Use a channel to write out the ByteBuffer. This will automatically empty the buffer.
+      WritableByteChannel channel = null;
+      try {
+        channel = (WritableByteChannel) UnsafeUtil.getObject(output, CHANNEL_FIELD_OFFSET);
+      } catch (ClassCastException e) {
+        // Absorb.
+      }
+      if (channel != null) {
+        channel.write(buffer);
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private static Class<?> safeGetClass(String className) {
+    try {
+      return Class.forName(className);
+    } catch (ClassNotFoundException e) {
+      return null;
+    }
+  }
+  private static long getChannelFieldOffset(Class<?> clazz) {
+    try {
+      if (clazz != null && UnsafeUtil.hasUnsafeArrayOperations()) {
+        Field field = clazz.getDeclaredField("channel");
+        return UnsafeUtil.objectFieldOffset(field);
+      }
+    } catch (Throwable e) {
+      // Absorb
+    }
+    return -1;
+  }
 }

+ 1 - 1
java/core/src/main/java/com/google/protobuf/MapFieldLite.java

@@ -58,7 +58,7 @@ public final class MapFieldLite<K, V> extends LinkedHashMap<K, V> {
   }
 
   @SuppressWarnings({"rawtypes", "unchecked"})
-  private static final MapFieldLite EMPTY_MAP_FIELD = new MapFieldLite(Collections.emptyMap());
+  private static final MapFieldLite EMPTY_MAP_FIELD = new MapFieldLite();
   static {
     EMPTY_MAP_FIELD.makeImmutable();
   }

+ 30 - 2
java/lite/pom.xml

@@ -75,11 +75,39 @@
       </plugin>
 
       <!-- Only compile a subset of the files -->
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-generated-sources</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${generated.sources.lite.dir}</source>
+              </sources>
+            </configuration>
+          </execution>
+          <execution>
+            <id>add-generated-test-sources</id>
+            <phase>generate-test-sources</phase>
+            <goals>
+              <goal>add-test-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${generated.testsources.lite.dir}</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
       <plugin>
         <artifactId>maven-compiler-plugin</artifactId>
         <configuration>
-          <generatedSourcesDirectory>${generated.sources.lite.dir}</generatedSourcesDirectory>
-          <generatedTestSourcesDirectory>${generated.testsources.lite.dir}</generatedTestSourcesDirectory>
           <includes>
             <include>**/AbstractMessageLite.java</include>
             <include>**/AbstractParser.java</include>

+ 1 - 1
java/pom.xml

@@ -94,7 +94,7 @@
       <plugins>
         <plugin>
           <artifactId>maven-compiler-plugin</artifactId>
-          <version>3.3</version>
+          <version>3.6.0</version>
           <configuration>
             <source>1.6</source>
             <target>1.6</target>

+ 17 - 5
java/util/pom.xml

@@ -79,12 +79,24 @@
         </executions>
       </plugin>
 
+      <!-- Add the generated test sources to the build -->
       <plugin>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <configuration>
-          <!-- Add the generated test sources to the build -->
-          <generatedTestSourcesDirectory>${generated.testsources.dir}</generatedTestSourcesDirectory>
-        </configuration>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-generated-test-sources</id>
+            <phase>generate-test-sources</phase>
+            <goals>
+              <goal>add-test-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${generated.testsources.dir}</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
       </plugin>
 
       <!-- Configure the OSGI bundle -->

+ 2 - 2
javanano/src/main/java/com/google/protobuf/nano/InternalNano.java

@@ -67,8 +67,8 @@ public final class InternalNano {
   public static final int TYPE_SINT32   = 17;
   public static final int TYPE_SINT64   = 18;
 
-  protected static final Charset UTF_8 = Charset.forName("UTF-8");
-  protected static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
+  static final Charset UTF_8 = Charset.forName("UTF-8");
+  static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
 
   private InternalNano() {}
 

+ 1 - 1
javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java

@@ -48,7 +48,7 @@ public class InvalidProtocolBufferNanoException extends IOException {
   static InvalidProtocolBufferNanoException truncatedMessage() {
     return new InvalidProtocolBufferNanoException(
       "While parsing a protocol message, the input ended unexpectedly " +
-      "in the middle of a field.  This could mean either than the " +
+      "in the middle of a field.  This could mean either that the " +
       "input has been truncated or that an embedded message " +
       "misreported its own length.");
   }

+ 1 - 1
jenkins/buildcmds/pull_request_32.sh

@@ -12,5 +12,5 @@
 export DOCKERFILE_DIR=jenkins/docker32
 export DOCKER_RUN_SCRIPT=jenkins/pull_request_in_docker.sh
 export OUTPUT_DIR=testoutput
-export TEST_SET="php_all"
+export TEST_SET="php_all_32"
 ./jenkins/build_and_run_docker.sh

+ 1 - 0
jenkins/docker/Dockerfile

@@ -113,6 +113,7 @@ ENV MVN mvn --batch-mode
 RUN cd /tmp && \
   git clone https://github.com/google/protobuf.git && \
   cd protobuf && \
+  git reset bf379715c93b581eeb078cec1f0dd8a7d79df431 && \
   ./autogen.sh && \
   ./configure && \
   make -j6 && \

+ 4 - 1
jenkins/docker32/Dockerfile

@@ -64,6 +64,7 @@ RUN php -r "unlink('composer-setup.php');"
 RUN cd /tmp && \
   git clone https://github.com/google/protobuf.git && \
   cd protobuf && \
+  git reset 734930f9197b7bc97c3c794c7a949fee2a08c280 && \
   ln -sfn /usr/bin/php5.5 /usr/bin/php && \
   ln -sfn /usr/bin/php-config5.5 /usr/bin/php-config && \
   ln -sfn /usr/bin/phpize5.5 /usr/bin/phpize && \
@@ -83,7 +84,9 @@ RUN wget http://am1.php.net/get/php-5.5.38.tar.bz2/from/this/mirror
 RUN mv mirror php-5.5.38.tar.bz2
 RUN tar -xvf php-5.5.38.tar.bz2
 RUN cd php-5.5.38 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-5.5-zts && \
-    make && make install
+    make && make install && make clean && cd ..
+RUN cd php-5.5.38 && ./configure --enable-bcmath --prefix=/usr/local/php-5.5-bc && \
+    make && make install && make clean && cd ..
 
 ##################
 # Python dependencies

+ 25 - 12
js/binary/decoder.js

@@ -941,11 +941,9 @@ jspb.BinaryDecoder.prototype.readEnum = function() {
 
 /**
  * Reads and parses a UTF-8 encoded unicode string from the stream.
- * The code is inspired by maps.vectortown.parse.StreamedDataViewReader, with
- * the exception that the implementation here does not get confused if it
- * encounters characters longer than three bytes. These characters are ignored
- * though, as they are extremely rare: three UTF-8 bytes cover virtually all
- * characters in common use (http://en.wikipedia.org/wiki/UTF-8).
+ * The code is inspired by maps.vectortown.parse.StreamedDataViewReader.
+ * Supports codepoints from U+0000 up to U+10FFFF. 
+ * (http://en.wikipedia.org/wiki/UTF-8).
  * @param {number} length The length of the string to read.
  * @return {string} The decoded string.
  */
@@ -953,30 +951,45 @@ jspb.BinaryDecoder.prototype.readString = function(length) {
   var bytes = this.bytes_;
   var cursor = this.cursor_;
   var end = cursor + length;
-  var chars = [];
+  var codeUnits = [];
 
   while (cursor < end) {
     var c = bytes[cursor++];
     if (c < 128) { // Regular 7-bit ASCII.
-      chars.push(c);
+      codeUnits.push(c);
     } else if (c < 192) {
       // UTF-8 continuation mark. We are out of sync. This
       // might happen if we attempted to read a character
-      // with more than three bytes.
+      // with more than four bytes.
       continue;
     } else if (c < 224) { // UTF-8 with two bytes.
       var c2 = bytes[cursor++];
-      chars.push(((c & 31) << 6) | (c2 & 63));
+      codeUnits.push(((c & 31) << 6) | (c2 & 63));
     } else if (c < 240) { // UTF-8 with three bytes.
       var c2 = bytes[cursor++];
       var c3 = bytes[cursor++];
-      chars.push(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+      codeUnits.push(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+    } else if (c < 248) { // UTF-8 with 4 bytes.
+      var c2 = bytes[cursor++];
+      var c3 = bytes[cursor++];
+      var c4 = bytes[cursor++];
+      // Characters written on 4 bytes have 21 bits for a codepoint. 
+      // We can't fit that on 16bit characters, so we use surrogates.
+      var codepoint = ((c & 7) << 18) | ((c2 & 63) << 12) | ((c3 & 63) << 6) | (c4 & 63);
+      // Surrogates formula from wikipedia.
+      // 1. Subtract 0x10000 from codepoint
+      codepoint -= 0x10000;
+      // 2. Split this into the high 10-bit value and the low 10-bit value
+      // 3. Add 0xD800 to the high value to form the high surrogate
+      // 4. Add 0xDC00 to the low value to form the low surrogate:
+      var low = (codepoint & 1023) + 0xDC00;
+      var high = ((codepoint >> 10) & 1023) + 0xD800;
+      codeUnits.push(high, low)
     }
   }
-
   // String.fromCharCode.apply is faster than manually appending characters on
   // Chrome 25+, and generates no additional cons string garbage.
-  var result = String.fromCharCode.apply(null, chars);
+  var result = String.fromCharCode.apply(null, codeUnits);
   this.cursor_ = cursor;
   return result;
 };

+ 23 - 0
js/binary/decoder_test.js

@@ -209,7 +209,30 @@ describe('binaryDecoderTest', function() {
     assertEquals(hashC, decoder.readFixedHash64());
     assertEquals(hashD, decoder.readFixedHash64());
   });
+  
+  /**
+   * Test encoding and decoding utf-8.
+   */
+   it('testUtf8', function() {
+    var encoder = new jspb.BinaryEncoder();
 
+    var ascii = "ASCII should work in 3, 2, 1..."
+    var utf8_two_bytes = "©";
+    var utf8_three_bytes = "❄";
+    var utf8_four_bytes = "😁";
+    
+    encoder.writeString(ascii);
+    encoder.writeString(utf8_two_bytes);
+    encoder.writeString(utf8_three_bytes);
+    encoder.writeString(utf8_four_bytes);
+    
+    var decoder = jspb.BinaryDecoder.alloc(encoder.end());
+    
+    assertEquals(ascii, decoder.readString(ascii.length));
+    assertEquals(utf8_two_bytes, decoder.readString(utf8_two_bytes.length));
+    assertEquals(utf8_three_bytes, decoder.readString(utf8_three_bytes.length));
+    assertEquals(utf8_four_bytes, decoder.readString(utf8_four_bytes.length));
+   });
 
   /**
    * Verifies that misuse of the decoder class triggers assertions.

+ 23 - 6
js/binary/encoder.js

@@ -452,19 +452,36 @@ jspb.BinaryEncoder.prototype.writeFixedHash64 = function(hash) {
  */
 jspb.BinaryEncoder.prototype.writeString = function(value) {
   var oldLength = this.buffer_.length;
-
-  // UTF16 to UTF8 conversion loop swiped from goog.crypt.stringToUtf8ByteArray.
+ 
   for (var i = 0; i < value.length; i++) {
+    
     var c = value.charCodeAt(i);
+
     if (c < 128) {
       this.buffer_.push(c);
     } else if (c < 2048) {
       this.buffer_.push((c >> 6) | 192);
       this.buffer_.push((c & 63) | 128);
-    } else {
-      this.buffer_.push((c >> 12) | 224);
-      this.buffer_.push(((c >> 6) & 63) | 128);
-      this.buffer_.push((c & 63) | 128);
+    } else if (c < 65536) {
+      // Look for surrogates
+      if (c >= 0xD800 && c <= 0xDBFF && i + 1 < value.length) {
+        var second = value.charCodeAt(i + 1);
+        if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate
+          // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
+          c = (c - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
+
+          this.buffer_.push((c >> 18) | 240);
+          this.buffer_.push(((c >> 12) & 63 ) | 128);
+          this.buffer_.push(((c >> 6) & 63) | 128);
+          this.buffer_.push((c & 63) | 128);
+          i++;
+        }
+      }
+      else {
+        this.buffer_.push((c >> 12) | 224);
+        this.buffer_.push(((c >> 6) & 63) | 128);
+        this.buffer_.push((c & 63) | 128);
+      }
     }
   }
 

+ 1 - 1
js/package.json

@@ -22,5 +22,5 @@
     "url": "https://github.com/google/protobuf/tree/master/js"
   },
   "author": "Google Protocol Buffers Team",
-  "license": "Apache-2.0"
+  "license" : "BSD-3-Clause"
 }

+ 21 - 0
objectivec/GPBCodedInputStream.h

@@ -217,6 +217,27 @@ CF_EXTERN_C_END
  **/
 - (size_t)position;
 
+/**
+ * Moves the limit to the given byte offset starting at the current location.
+ *
+ * @exception GPBCodedInputStreamException If the requested bytes exceeed the
+ *            current limit.
+ *
+ * @param byteLimit The number of bytes to move the limit, offset to the current
+ *                  location.
+ *
+ * @return The limit offset before moving the new limit.
+ */
+- (size_t)pushLimit:(size_t)byteLimit;
+
+/**
+ * Moves the limit back to the offset as it was before calling pushLimit:.
+ *
+ * @param oldLimit The number of bytes to move the current limit. Usually this
+ *                 is the value returned by the pushLimit: method.
+ */
+- (void)popLimit:(size_t)oldLimit;
+
 /**
  * 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.

+ 8 - 0
objectivec/GPBCodedInputStream.m

@@ -400,6 +400,14 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state,
   return state_.bufferPos;
 }
 
+- (size_t)pushLimit:(size_t)byteLimit {
+  return GPBCodedInputStreamPushLimit(&state_, byteLimit);
+}
+
+- (void)popLimit:(size_t)oldLimit {
+  GPBCodedInputStreamPopLimit(&state_, oldLimit);
+}
+
 - (double)readDouble {
   return GPBCodedInputStreamReadDouble(&state_);
 }

+ 10 - 1
objectivec/GPBMessage.h

@@ -65,9 +65,18 @@ CF_EXTERN_C_END
 
 /**
  * Base class that each generated message subclasses from.
+ *
+ * @note While the class support NSSecureCoding, if the message has any
+ *       extensions, they will end up reloaded in @c unknownFields as there is
+ *       no way for the @c NSCoding plumbing to pass through a
+ *       @c GPBExtensionRegistry. To support extensions, instead of passing the
+ *       calls off to the Message, simple store the result of @c data, and then
+ *       when loading, fetch the data and use
+ *       @c +parseFromData:extensionRegistry:error: to provide an extension
+ *       registry.
  **/
 @interface GPBMessage : NSObject<NSSecureCoding, NSCopying>
- 
+
 // If you add an instance method/property to this class that may conflict with
 // fields declared in protos, you need to update objective_helpers.cc. The main
 // cases are methods that take no arguments, or setFoo:/hasFoo: type methods.

+ 1 - 1
objectivec/README.md

@@ -44,7 +44,7 @@ Add `objectivec/\*.h` & `objectivec/\*.m` except for
 If the target is using ARC, remember to turn off ARC (`-fno-objc-arc`) for the
 `.m` files.
 
-The files generated by `protoc` for the `*.proto` files (`\*.pbobjc.h' and
+The files generated by `protoc` for the `*.proto` files (`\*.pbobjc.h` and
 `\*.pbobjc.m`) are then also added to the target.
 
 Usage

+ 125 - 2
php/ext/google/protobuf/array.c

@@ -54,6 +54,16 @@ static zend_function_entry repeated_field_methods[] = {
   PHP_ME(RepeatedField, offsetSet,    arginfo_offsetSet, ZEND_ACC_PUBLIC)
   PHP_ME(RepeatedField, offsetUnset,  arginfo_offsetGet, ZEND_ACC_PUBLIC)
   PHP_ME(RepeatedField, count,        arginfo_void,      ZEND_ACC_PUBLIC)
+  PHP_ME(RepeatedField, getIterator,  arginfo_void,      ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static zend_function_entry repeated_field_iter_methods[] = {
+  PHP_ME(RepeatedFieldIter, rewind,      arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(RepeatedFieldIter, current,     arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(RepeatedFieldIter, key,         arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(RepeatedFieldIter, next,        arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(RepeatedFieldIter, valid,       arginfo_void, ZEND_ACC_PUBLIC)
   ZEND_FE_END
 };
 
@@ -70,11 +80,15 @@ static int repeated_field_has_dimension(zval *object, zval *offset TSRMLS_DC);
 static HashTable *repeated_field_get_gc(zval *object, zval ***table,
                                         int *n TSRMLS_DC);
 
+static zend_object_value repeated_field_iter_create(zend_class_entry *ce TSRMLS_DC);
+static void repeated_field_iter_free(void *object TSRMLS_DC);
+
 // -----------------------------------------------------------------------------
 // RepeatedField creation/desctruction
 // -----------------------------------------------------------------------------
 
 zend_class_entry* repeated_field_type;
+zend_class_entry* repeated_field_iter_type;
 zend_object_handlers* repeated_field_handlers;
 
 void repeated_field_init(TSRMLS_D) {
@@ -86,8 +100,8 @@ void repeated_field_init(TSRMLS_D) {
   repeated_field_type = zend_register_internal_class(&class_type TSRMLS_CC);
   repeated_field_type->create_object = repeated_field_create;
 
-  zend_class_implements(repeated_field_type TSRMLS_CC, 2, spl_ce_ArrayAccess,
-                        spl_ce_Countable);
+  zend_class_implements(repeated_field_type TSRMLS_CC, 3, spl_ce_ArrayAccess,
+                        zend_ce_aggregate, spl_ce_Countable);
 
   repeated_field_handlers = PEMALLOC(zend_object_handlers);
   memcpy(repeated_field_handlers, zend_get_std_object_handlers(),
@@ -386,3 +400,112 @@ PHP_METHOD(RepeatedField, count) {
 
   RETURN_LONG(zend_hash_num_elements(HASH_OF(intern->array)));
 }
+
+/**
+ * Return the beginning iterator.
+ * This will also be called for: foreach($arr)
+ * @return object Beginning iterator.
+ */
+PHP_METHOD(RepeatedField, getIterator) {
+  zval *iter_php = NULL;
+  MAKE_STD_ZVAL(iter_php);
+  Z_TYPE_P(iter_php) = IS_OBJECT;
+  Z_OBJVAL_P(iter_php) = repeated_field_iter_type->create_object(
+      repeated_field_iter_type TSRMLS_CC);
+
+  RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
+  RepeatedFieldIter *iter = zend_object_store_get_object(iter_php TSRMLS_CC);
+  iter->repeated_field = intern;
+  iter->position = 0;
+
+  RETURN_ZVAL(iter_php, 1, 1);
+}
+
+// -----------------------------------------------------------------------------
+// RepeatedFieldIter creation/desctruction
+// -----------------------------------------------------------------------------
+
+void repeated_field_iter_init(TSRMLS_D) {
+  zend_class_entry class_type;
+  const char* class_name = "Google\\Protobuf\\Internal\\RepeatedFieldIter";
+  INIT_CLASS_ENTRY_EX(class_type, class_name, strlen(class_name),
+                      repeated_field_iter_methods);
+
+  repeated_field_iter_type =
+      zend_register_internal_class(&class_type TSRMLS_CC);
+  repeated_field_iter_type->create_object = repeated_field_iter_create;
+
+  zend_class_implements(repeated_field_iter_type TSRMLS_CC, 1,
+                        zend_ce_iterator);
+}
+
+static zend_object_value repeated_field_iter_create(
+    zend_class_entry *ce TSRMLS_DC) {
+  zend_object_value retval = {0};
+  RepeatedFieldIter *intern;
+
+  intern = emalloc(sizeof(RepeatedFieldIter));
+  memset(intern, 0, sizeof(RepeatedFieldIter));
+
+  zend_object_std_init(&intern->std, ce TSRMLS_CC);
+  object_properties_init(&intern->std, ce);
+
+  intern->repeated_field = NULL;
+  intern->position = 0;
+
+  retval.handle = zend_objects_store_put(
+      intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
+      (zend_objects_free_object_storage_t)repeated_field_iter_free,
+      NULL TSRMLS_CC);
+  retval.handlers = zend_get_std_object_handlers();
+
+  return retval;
+}
+
+static void repeated_field_iter_free(void *object TSRMLS_DC) {
+  RepeatedFieldIter *intern = object;
+  zend_object_std_dtor(&intern->std TSRMLS_CC);
+  efree(object);
+}
+
+// -----------------------------------------------------------------------------
+// PHP RepeatedFieldIter Methods
+// -----------------------------------------------------------------------------
+
+PHP_METHOD(RepeatedFieldIter, rewind) {
+  RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
+  intern->position = 0;
+}
+
+PHP_METHOD(RepeatedFieldIter, current) {
+  RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
+  RepeatedField *repeated_field = intern->repeated_field;
+
+  long index;
+  void *memory;
+
+  HashTable *table = HASH_OF(repeated_field->array);
+
+  if (zend_hash_index_find(table, intern->position, (void **)&memory) ==
+      FAILURE) {
+    zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
+    return;
+  }
+  native_slot_get(repeated_field->type, memory, return_value_ptr TSRMLS_CC);
+}
+
+PHP_METHOD(RepeatedFieldIter, key) {
+  RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
+  RETURN_LONG(intern->position);
+}
+
+PHP_METHOD(RepeatedFieldIter, next) {
+  RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
+  ++intern->position;
+}
+
+PHP_METHOD(RepeatedFieldIter, valid) {
+  RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
+  RETURN_BOOL(zend_hash_num_elements(HASH_OF(intern->repeated_field->array)) >
+              intern->position);
+}

+ 34 - 21
php/ext/google/protobuf/def.c

@@ -250,28 +250,41 @@ PHP_METHOD(DescriptorPool, getGeneratedPool) {
   RETURN_ZVAL(generated_pool_php, 1, 0);
 }
 
-static void convert_to_class_name_inplace(char *proto_name,
-                                          size_t pkg_name_len) {
+static void convert_to_class_name_inplace(char *class_name,
+                                          const char* fullname,
+                                          const char* package_name) {
   size_t i;
   bool first_char = false;
+  size_t pkg_name_len = package_name == NULL ? 0 : strlen(package_name);
 
-  for (i = 0; i <= pkg_name_len + 1; i++) {
-    // PHP package uses camel case.
-    if (!first_char && proto_name[i] != '.') {
-      first_char = true;
-      proto_name[i] += 'A' - 'a';
-    }
-    // php packages are divided by '\'.
-    if (proto_name[i] == '.') {
-      first_char = false;
-      proto_name[i] = '\\';
+  // In php, class name cannot be Empty.
+  if (strcmp("google.protobuf.Empty", fullname) == 0) {
+    fullname = "google.protobuf.GPBEmpty";
+  }
+
+  if (pkg_name_len == 0) {
+    strcpy(class_name, fullname);
+  } else {
+    class_name[0] = '.';
+    strcpy(&class_name[1], fullname);
+    for (i = 0; i <= pkg_name_len + 1; i++) {
+      // PHP package uses camel case.
+      if (!first_char && class_name[i] != '.') {
+        first_char = true;
+        class_name[i] += 'A' - 'a';
+      }
+      // php packages are divided by '\'.
+      if (class_name[i] == '.') {
+        first_char = false;
+        class_name[i] = '\\';
+      }
     }
   }
 
   // Submessage is concatenated with its containing messages by '_'.
-  for (i = pkg_name_len; i < strlen(proto_name); i++) {
-    if (proto_name[i] == '.') {
-      proto_name[i] = '_';
+  for (i = pkg_name_len; i < strlen(class_name); i++) {
+    if (class_name[i] == '.') {
+      class_name[i] = '_';
     }
   }
 }
@@ -322,13 +335,13 @@ PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {
         upb_msgdef_mapentry(upb_downcast_msgdef(def))) {                       \
       break;                                                                   \
     }                                                                          \
-    /* Prepend '.' to package name to make it absolute. */                     \
+    /* Prepend '.' to package name to make it absolute. In the 5 additional    \
+     * bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if    \
+     * given message is google.protobuf.Empty.*/                               \
     const char *fullname = upb_##def_type_lower##_fullname(def_type_lower);    \
-    char *klass_name = ecalloc(sizeof(char), 2 + strlen(fullname));            \
-    klass_name[0] = '.';                                                       \
-    strcpy(&klass_name[1], fullname);                                          \
-    size_t pkg_name_len = strlen(upb_filedef_package(files[0]));               \
-    convert_to_class_name_inplace(klass_name, pkg_name_len);                   \
+    char *klass_name = ecalloc(sizeof(char), 5 + strlen(fullname));            \
+    convert_to_class_name_inplace(klass_name, fullname,                        \
+                                  upb_filedef_package(files[0]));              \
     zend_class_entry **pce;                                                    \
     if (zend_lookup_class(klass_name, strlen(klass_name), &pce TSRMLS_CC) ==   \
         FAILURE) {                                                             \

+ 2 - 2
php/ext/google/protobuf/message.c

@@ -177,8 +177,8 @@ static zend_object_value message_create(zend_class_entry* ce TSRMLS_DC) {
 
   zend_object_std_init(&msg->std, ce TSRMLS_CC);
   object_properties_init(&msg->std, ce);
-  layout_init(desc->layout, message_data(msg), msg->std.properties_table
-	      TSRMLS_CC);
+  layout_init(desc->layout, message_data(msg),
+              msg->std.properties_table TSRMLS_CC);
 
   return_value.handle = zend_objects_store_put(
       msg, (zend_objects_store_dtor_t)zend_objects_destroy_object, message_free,

+ 1 - 0
php/ext/google/protobuf/protobuf.c

@@ -156,6 +156,7 @@ static PHP_RSHUTDOWN_FUNCTION(protobuf) {
 static PHP_MINIT_FUNCTION(protobuf) {
   map_field_init(TSRMLS_C);
   repeated_field_init(TSRMLS_C);
+  repeated_field_iter_init(TSRMLS_C);
   gpb_type_init(TSRMLS_C);
   message_init(TSRMLS_C);
   descriptor_pool_init(TSRMLS_C);

+ 19 - 0
php/ext/google/protobuf/protobuf.h

@@ -39,6 +39,9 @@
 #define PHP_PROTOBUF_EXTNAME "protobuf"
 #define PHP_PROTOBUF_VERSION "3.1.0a1"
 
+#define MAX_LENGTH_OF_INT64 20
+#define SIZEOF_INT64 8
+
 // -----------------------------------------------------------------------------
 // Forward Declaration
 // ----------------------------------------------------------------------------
@@ -51,6 +54,7 @@ struct MessageField;
 struct MessageHeader;
 struct MessageLayout;
 struct RepeatedField;
+struct RepeatedFieldIter;
 struct MapField;
 
 typedef struct DescriptorPool DescriptorPool;
@@ -61,6 +65,7 @@ typedef struct MessageField MessageField;
 typedef struct MessageHeader MessageHeader;
 typedef struct MessageLayout MessageLayout;
 typedef struct RepeatedField RepeatedField;
+typedef struct RepeatedFieldIter RepeatedFieldIter;
 typedef struct MapField MapField;
 
 // -----------------------------------------------------------------------------
@@ -77,6 +82,7 @@ void descriptor_pool_init(TSRMLS_D);
 void gpb_type_init(TSRMLS_D);
 void map_field_init(TSRMLS_D);
 void repeated_field_init(TSRMLS_D);
+void repeated_field_iter_init(TSRMLS_D);
 void util_init(TSRMLS_D);
 void message_init(TSRMLS_D);
 
@@ -366,6 +372,12 @@ struct RepeatedField {
                                    // (for message field only).
 };
 
+struct RepeatedFieldIter {
+  zend_object std;
+  RepeatedField* repeated_field;
+  long position;
+};
+
 void repeated_field_create_with_type(zend_class_entry* ce,
                                      const upb_fielddef* field,
                                      zval** repeated_field TSRMLS_DC);
@@ -383,6 +395,13 @@ PHP_METHOD(RepeatedField, offsetGet);
 PHP_METHOD(RepeatedField, offsetSet);
 PHP_METHOD(RepeatedField, offsetUnset);
 PHP_METHOD(RepeatedField, count);
+PHP_METHOD(RepeatedField, getIterator);
+
+PHP_METHOD(RepeatedFieldIter, rewind);
+PHP_METHOD(RepeatedFieldIter, current);
+PHP_METHOD(RepeatedFieldIter, key);
+PHP_METHOD(RepeatedFieldIter, next);
+PHP_METHOD(RepeatedFieldIter, valid);
 
 // -----------------------------------------------------------------------------
 // Oneof Field.

+ 22 - 2
php/ext/google/protobuf/storage.c

@@ -174,11 +174,31 @@ CASE(FLOAT,  DOUBLE, float)
 CASE(DOUBLE, DOUBLE, double)
 CASE(BOOL,   BOOL,   int8_t)
 CASE(INT32,  LONG,   int32_t)
-CASE(INT64,  LONG,   int64_t)
-CASE(UINT64, LONG,   uint64_t)
 CASE(ENUM,   LONG,   uint32_t)
 
 #undef CASE
+
+#if SIZEOF_LONG == 4
+#define CASE(upb_type, c_type)                        \
+    case UPB_TYPE_##upb_type: {                       \
+      SEPARATE_ZVAL_IF_NOT_REF(cache);                \
+      char buffer[MAX_LENGTH_OF_INT64];               \
+      sprintf(buffer, "%lld", DEREF(memory, c_type)); \
+      ZVAL_STRING(*cache, buffer, 1);                 \
+      return;                                         \
+    }
+#else
+#define CASE(upb_type, c_type)                        \
+    case UPB_TYPE_##upb_type: {                       \
+      SEPARATE_ZVAL_IF_NOT_REF(cache);                \
+      ZVAL_LONG(*cache, DEREF(memory, c_type));       \
+      return;                                         \
+    }
+#endif
+CASE(UINT64, uint64_t)
+CASE(INT64,  int64_t)
+#undef CASE
+
     case UPB_TYPE_UINT32: {
       // Prepend bit-1 for negative numbers, so that uint32 value will be
       // consistent on both 32-bit and 64-bit architectures.

+ 130 - 9
php/ext/google/protobuf/type_check.c

@@ -34,6 +34,7 @@
 #include "utf8.h"
 
 static zend_class_entry* util_type;
+static const char int64_min_digits[] = "9223372036854775808";
 
 ZEND_BEGIN_ARG_INFO_EX(arg_check_optional, 0, 0, 1)
   ZEND_ARG_INFO(1, val)
@@ -78,8 +79,128 @@ void util_init(TSRMLS_D) {
 // Type checking/conversion.
 // -----------------------------------------------------------------------------
 
+// This is modified from is_numeric_string in zend_operators.h. The behavior of 
+// this function is the same as is_numeric_string, except that this takes
+// int64_t as input instead of long.
+static zend_uchar convert_numeric_string(
+    const char *str, int length, int64_t *lval, double *dval) {
+  const char *ptr;
+  int base = 10, digits = 0, dp_or_e = 0;
+  double local_dval = 0.0;
+  zend_uchar type;
+
+  if (length == 0) {
+    return IS_NULL;
+  }
+
+  while (*str == ' ' || *str == '\t' || *str == '\n' || 
+         *str == '\r' || *str == '\v' || *str == '\f') {
+    str++;
+    length--;
+  }
+  ptr = str;
+
+  if (*ptr == '-' || *ptr == '+') {
+    ptr++;
+  }
+
+  if (ZEND_IS_DIGIT(*ptr)) {
+    // Handle hex numbers
+    // str is used instead of ptr to disallow signs and keep old behavior.
+    if (length > 2 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) {
+      base = 16;
+      ptr += 2;
+    }
+
+    // Skip any leading 0s.
+    while (*ptr == '0') {
+      ptr++;
+    }
+
+    // Count the number of digits. If a decimal point/exponent is found,
+    // it's a double. Otherwise, if there's a dval or no need to check for
+    // a full match, stop when there are too many digits for a int64 */
+    for (type = IS_LONG;
+        !(digits >= MAX_LENGTH_OF_INT64 && dval);
+        digits++, ptr++) {
+check_digits:
+      if (ZEND_IS_DIGIT(*ptr) || (base == 16 && ZEND_IS_XDIGIT(*ptr))) {
+        continue;
+      } else if (base == 10) {
+        if (*ptr == '.' && dp_or_e < 1) {
+          goto process_double;
+        } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {
+          const char *e = ptr + 1;
+
+          if (*e == '-' || *e == '+') {
+            ptr = e++;
+          }
+          if (ZEND_IS_DIGIT(*e)) {
+            goto process_double;
+          }
+        }
+      }
+      break;
+    }
+
+    if (base == 10) {
+      if (digits >= MAX_LENGTH_OF_INT64) {
+        dp_or_e = -1;
+        goto process_double;
+      }
+    } else if (!(digits < SIZEOF_INT64 * 2 ||
+               (digits == SIZEOF_INT64 * 2 && ptr[-digits] <= '7'))) {
+      if (dval) {
+        local_dval = zend_hex_strtod(str, &ptr);
+      }
+      type = IS_DOUBLE;
+    }
+  } else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) {
+process_double:
+    type = IS_DOUBLE;
+
+    // If there's a dval, do the conversion; else continue checking
+    // the digits if we need to check for a full match.
+    if (dval) {
+      local_dval = zend_strtod(str, &ptr);
+    } else if (dp_or_e != -1) {
+      dp_or_e = (*ptr++ == '.') ? 1 : 2;
+      goto check_digits;
+    }
+  } else {
+    return IS_NULL;
+  }
+  if (ptr != str + length) {
+    zend_error(E_NOTICE, "A non well formed numeric value encountered");
+    return 0;
+  }
+
+  if (type == IS_LONG) {
+    if (digits == MAX_LENGTH_OF_INT64 - 1) {
+      int cmp = strcmp(&ptr[-digits], int64_min_digits);
+
+      if (!(cmp < 0 || (cmp == 0 && *str == '-'))) {
+        if (dval) {
+          *dval = zend_strtod(str, NULL);
+        }
+
+	return IS_DOUBLE;
+      }
+    }
+    if (lval) {
+      *lval = strtoll(str, NULL, base);
+    }
+    return IS_LONG;
+  } else {
+    if (dval) {
+      *dval = local_dval;
+    }
+    return IS_DOUBLE;
+  }
+}
+
 #define CONVERT_TO_INTEGER(type)                                             \
-  static bool convert_long_to_##type(long val, type##_t* type##_value) {     \
+  static bool convert_int64_to_##type(int64_t val, type##_t* type##_value) { \
     *type##_value = (type##_t)val;                                           \
     return true;                                                             \
   }                                                                          \
@@ -91,15 +212,15 @@ void util_init(TSRMLS_D) {
                                                                              \
   static bool convert_string_to_##type(const char* val, int len,             \
                                        type##_t* type##_value) {             \
-    long lval;                                                               \
+    int64_t lval;                                                            \
     double dval;                                                             \
                                                                              \
-    switch (is_numeric_string(val, len, &lval, &dval, 0)) {                  \
+    switch (convert_numeric_string(val, len, &lval, &dval)) {                \
       case IS_DOUBLE: {                                                      \
         return convert_double_to_##type(dval, type##_value);                 \
       }                                                                      \
       case IS_LONG: {                                                        \
-        return convert_long_to_##type(lval, type##_value);                   \
+        return convert_int64_to_##type(lval, type##_value);                  \
       }                                                                      \
       default:                                                               \
         zend_error(E_USER_ERROR,                                             \
@@ -111,7 +232,7 @@ void util_init(TSRMLS_D) {
   bool protobuf_convert_to_##type(zval* from, type##_t* to) {                \
     switch (Z_TYPE_P(from)) {                                                \
       case IS_LONG: {                                                        \
-        return convert_long_to_##type(Z_LVAL_P(from), to);                   \
+        return convert_int64_to_##type(Z_LVAL_P(from), to);                  \
       }                                                                      \
       case IS_DOUBLE: {                                                      \
         return convert_double_to_##type(Z_DVAL_P(from), to);                 \
@@ -137,7 +258,7 @@ CONVERT_TO_INTEGER(uint64);
 #undef CONVERT_TO_INTEGER
 
 #define CONVERT_TO_FLOAT(type)                                              \
-  static bool convert_long_to_##type(long val, type* type##_value) {        \
+  static bool convert_int64_to_##type(int64_t val, type* type##_value) {    \
     *type##_value = (type)val;                                              \
     return true;                                                            \
   }                                                                         \
@@ -149,10 +270,10 @@ CONVERT_TO_INTEGER(uint64);
                                                                             \
   static bool convert_string_to_##type(const char* val, int len,            \
                                        type* type##_value) {                \
-    long lval;                                                              \
+    int64_t lval;                                                           \
     double dval;                                                            \
                                                                             \
-    switch (is_numeric_string(val, len, &lval, &dval, 0)) {                 \
+    switch (convert_numeric_string(val, len, &lval, &dval)) {               \
       case IS_DOUBLE: {                                                     \
         *type##_value = (type)dval;                                         \
         return true;                                                        \
@@ -171,7 +292,7 @@ CONVERT_TO_INTEGER(uint64);
   bool protobuf_convert_to_##type(zval* from, type* to) {                   \
     switch (Z_TYPE_P(from)) {                                               \
       case IS_LONG: {                                                       \
-        return convert_long_to_##type(Z_LVAL_P(from), to);                  \
+        return convert_int64_to_##type(Z_LVAL_P(from), to);                 \
       }                                                                     \
       case IS_DOUBLE: {                                                     \
         return convert_double_to_##type(Z_DVAL_P(from), to);                \

+ 38 - 3
php/src/Google/Protobuf/Internal/GPBUtil.php

@@ -37,6 +37,28 @@ use Google\Protobuf\Internal\RepeatedField;
 
 class GPBUtil
 {
+    public function divideInt64ToInt32($value, &$high, &$low, $trim = false)
+    {
+        $isNeg = (bccomp($value, 0) < 0);
+        if ($isNeg) {
+            $value = bcsub(0, $value);
+        }
+        $high = (int) bcdiv(bcadd($value, 1), 4294967296);
+        $low = (int) bcmod($value, 4294967296);
+        if ($isNeg) {
+            $high = ~$high;
+            $low = ~$low;
+            $low++;
+            if (!$low) {
+                $high++;
+            }
+        }
+
+        if ($trim) {
+            $high = 0;
+        }
+    }
+
 
     public static function checkString(&$var, $check_utf8)
     {
@@ -70,9 +92,14 @@ class GPBUtil
     public static function checkUint32(&$var)
     {
         if (is_numeric($var)) {
-            $var = intval($var);
             if (PHP_INT_SIZE === 8) {
+                $var = intval($var);
                 $var |= ((-(($var >> 31) & 0x1)) & ~0xFFFFFFFF);
+            } else {
+                if (bccomp($var, 0x7FFFFFFF) > 0) {
+                    $var = bcsub($var, "4294967296");
+                }
+                $var = (int) $var;
             }
         } else {
             trigger_error("Expect integer.", E_USER_ERROR);
@@ -82,7 +109,11 @@ class GPBUtil
     public static function checkInt64(&$var)
     {
         if (is_numeric($var)) {
-            $var = intval($var);
+            if (PHP_INT_SIZE == 8) {
+                $var = intval($var);
+            } else {
+                $var = bcdiv($var, 1, 0);
+            }
         } else {
             trigger_error("Expect integer.", E_USER_ERROR);
         }
@@ -91,7 +122,11 @@ class GPBUtil
     public static function checkUint64(&$var)
     {
         if (is_numeric($var)) {
-            $var = intval($var);
+            if (PHP_INT_SIZE == 8) {
+                $var = intval($var);
+            } else {
+                $var = bcdiv($var, 1, 0);
+            }
         } else {
             trigger_error("Expect integer.", E_USER_ERROR);
         }

+ 23 - 24
php/src/Google/Protobuf/Internal/GPBWire.php

@@ -32,10 +32,6 @@
 
 namespace Google\Protobuf\Internal;
 
-use Google\Protobuf\Internal\GPBUtil;
-use Google\Protobuf\Internal\Int64;
-use Google\Protobuf\Internal\Uint64;
-
 class GPBWire
 {
 
@@ -150,20 +146,28 @@ class GPBWire
 
     public static function zigZagEncode64($int64)
     {
-        $a = $int64->copy()->leftShift(1);
-        $b = $int64->copy()->rightShift(63);
-        $result = $a->bitXor($b);
-        $uint64 = Uint64::newValue($result->high, $result->low);
-        return $uint64;
+        if (PHP_INT_SIZE == 4) {
+            if (bccomp($int64, 0) >= 0) {
+                return bcmul($int64, 2);
+            } else {
+                return bcsub(bcmul(bcsub(0, $int64), 2), 1);
+            }
+        } else {
+            return ($int64 << 1) ^ ($int64 >> 63);
+        }
     }
 
     public static function zigZagDecode64($uint64)
     {
-        $a = $uint64->copy()->rightShift(1);
-        $b = $uint64->oddMask();
-        $result = $a->bitXor($b);
-        $int64 = Int64::newValue($result->high, $result->low);
-        return $int64;
+        if (PHP_INT_SIZE == 4) {
+            if (bcmod($uint64, 2) == 0) {
+                return bcdiv($uint64, 2, 0);
+            } else {
+                return bcsub(0, bcdiv(bcadd($uint64, 1), 2, 0));
+            }
+        } else {
+            return (($uint64 >> 1) & 0x7FFFFFFFFFFFFFFF) ^ (-($uint64 & 1));
+        }
     }
 
     public static function readInt32(&$input, &$value)
@@ -227,11 +231,7 @@ class GPBWire
 
     public static function readSfixed64(&$input, &$value)
     {
-        if (!self::readFixed64($input, $value)) {
-            return false;
-        }
-        $value = Int64::newValue($value->high, $value->low);
-        return true;
+        return $input->readLittleEndian64($value);
     }
 
     public static function readFloat(&$input, &$value)
@@ -259,7 +259,7 @@ class GPBWire
         if (!$input->readVarint64($value)) {
             return false;
         }
-        if ($value->high === 0 && $value->low === 0) {
+        if ($value == 0) {
             $value = false;
         } else {
             $value = true;
@@ -324,8 +324,8 @@ class GPBWire
 
     public static function writeSint64(&$output, $value)
     {
-        $value = GPBWire::zigZagEncode64(GPBUtil::Int64($value));
-        return $output->writeVarint64($value->toInteger());
+        $value = GPBWire::zigZagEncode64($value);
+        return $output->writeVarint64($value);
     }
 
     public static function writeFixed32(&$output, $value)
@@ -431,9 +431,8 @@ class GPBWire
 
     public static function sint64Size($value)
     {
-        $value = GPBUtil::Int64($value);
         $value = self::zigZagEncode64($value);
-        return self::varint64Size($value->toInteger());
+        return self::varint64Size($value);
     }
 
     public static function varint64Size($value)

+ 58 - 8
php/src/Google/Protobuf/Internal/InputStream.php

@@ -34,6 +34,24 @@ namespace Google\Protobuf\Internal;
 
 use Google\Protobuf\Internal\Uint64;
 
+function combineInt32ToInt64($high, $low)
+{
+    $isNeg = $high < 0;
+    if ($isNeg) {
+        $high = ~$high;
+        $low = ~$low;
+        $low++;
+        if (!$low) {
+            $high++;
+        }
+    }
+    $result = bcadd(bcmul($high, 4294967296), $low);
+    if ($isNeg) {
+      $result = bcsub(0, $result);
+    }
+    return $result;
+}
+
 class InputStream
 {
 
@@ -116,11 +134,23 @@ class InputStream
         if (!$this->readVarint64($var)) {
             return false;
         }
-        $var = $var->toInteger() & 0xFFFFFFFF;
+
+        if (PHP_INT_SIZE == 4) {
+            $var = bcmod($var, 4294967296);
+        } else {
+            $var &= 0xFFFFFFFF;
+        }
+
         // Convert large uint32 to int32.
-        if (PHP_INT_SIZE === 8 && ($var > 0x7FFFFFFF)) {
-            $var = $var | (0xFFFFFFFF << 32);
+        if ($var > 0x7FFFFFFF) {
+            if (PHP_INT_SIZE === 8) {
+                $var = $var | (0xFFFFFFFF << 32);
+            } else {
+                $var = bcsub($var, 4294967296);
+            }
         }
+
+        $var = intval($var);
         return true;
     }
 
@@ -130,7 +160,8 @@ class InputStream
      */
     public function readVarint64(&$var)
     {
-        $result = new Uint64(0);
+        $high = 0;
+        $low = 0;
         $count = 0;
         $b = 0;
 
@@ -142,12 +173,27 @@ class InputStream
                 return false;
             }
             $b = ord($this->buffer[$this->current]);
-            $result->bitOr((new Uint64($b & 0x7F))->leftShift(7 * $count));
+            $bits = 7 * $count;
+            if ($bits >= 32) {
+                $high |= (($b & 0x7F) << ($bits - 32));
+            } else if ($bits > 25){
+                $high_bits = $bits - 25;
+                $low = ($low | (($b & 0x7F) << $bits)) & (int) 0xFFFFFFFF;
+                $high = $b & ((0x1 << $high_bits) -1);
+            } else {
+                $low |= (($b & 0x7F) << $bits);
+            }
+
             $this->advance(1);
             $count += 1;
         } while ($b & 0x80);
 
-        $var = $result;
+        if (PHP_INT_SIZE == 4) {
+            $var = combineInt32ToInt64($high, $low);
+        } else {
+            $var = ($high & 0xFFFFFFFF) << 32 |
+                   ($low & 0xFFFFFFFF);
+        }
         return true;
     }
 
@@ -161,7 +207,7 @@ class InputStream
         if (!$this->readVarint64($var)) {
             return false;
         }
-        $var = $var->toInteger();
+        $var = (int)$var;
         return true;
     }
 
@@ -197,7 +243,11 @@ class InputStream
             return false;
         }
         $high = unpack('V', $data)[1];
-        $var = Uint64::newValue($high, $low);
+        if (PHP_INT_SIZE == 4) {
+            $var = combineInt32ToInt64($high, $low);
+        } else {
+            $var = ($high << 32) | $low;
+        }
         return true;
     }
 

+ 10 - 5
php/src/Google/Protobuf/Internal/Message.php

@@ -125,6 +125,16 @@ class Message
                 $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
                 $oneof_name = $oneof->getName();
                 $this->$oneof_name = new OneofField($oneof);
+            } else if ($field->getLabel() === GPBLabel::OPTIONAL && 
+                       PHP_INT_SIZE == 4) {
+                switch ($field->getType()) {
+                    case GPBType::INT64:
+                    case GPBType::UINT64:
+                    case GPBType::FIXED64:
+                    case GPBType::SFIXED64:
+                    case GPBType::SINT64:
+                        $this->$setter("0");
+                }
             }
         }
     }
@@ -210,13 +220,11 @@ class Message
                 if (!GPBWire::readInt64($input, $value)) {
                     return false;
                 }
-                $value = $value->toInteger();
                 break;
             case GPBType::UINT64:
                 if (!GPBWire::readUint64($input, $value)) {
                     return false;
                 }
-                $value = $value->toInteger();
                 break;
             case GPBType::INT32:
                 if (!GPBWire::readInt32($input, $value)) {
@@ -227,7 +235,6 @@ class Message
                 if (!GPBWire::readFixed64($input, $value)) {
                     return false;
                 }
-                $value = $value->toInteger();
                 break;
             case GPBType::FIXED32:
                 if (!GPBWire::readFixed32($input, $value)) {
@@ -285,7 +292,6 @@ class Message
                 if (!GPBWire::readSfixed64($input, $value)) {
                     return false;
                 }
-                $value = $value->toInteger();
                 break;
             case GPBType::SINT32:
                 if (!GPBWire::readSint32($input, $value)) {
@@ -296,7 +302,6 @@ class Message
                 if (!GPBWire::readSint64($input, $value)) {
                     return false;
                 }
-                $value = $value->toInteger();
                 break;
             default:
                 user_error("Unsupported type.");

+ 36 - 15
php/src/Google/Protobuf/Internal/OutputStream.php

@@ -90,8 +90,6 @@ class OutputStream
     public function writeRaw($data, $size)
     {
         if ($this->buffer_size < $size) {
-            var_dump($this->buffer_size);
-            var_dump($size);
             trigger_error("Output stream doesn't have enough buffer.");
             return false;
         }
@@ -107,15 +105,28 @@ class OutputStream
     private static function writeVarintToArray($value, &$buffer, $trim = false)
     {
         $current = 0;
-        if ($trim) {
-            $value &= 0xFFFFFFFF;
+
+        $high = 0;
+        $low = 0;
+        if (PHP_INT_SIZE == 4) {
+            GPBUtil::divideInt64ToInt32($value, $high, $low, $trim);
+        } else {
+            if ($trim) {
+                $low = $value & 0xFFFFFFFF;
+            } else {
+                $low = $value;
+            }
         }
-        while ($value >= 0x80 || $value < 0) {
-            $buffer[$current] = chr($value | 0x80);
+
+        while ($low >= 0x80 || $low < 0) {
+            $buffer[$current] = chr($low | 0x80);
             $value = ($value >> 7) & ~(0x7F << ((PHP_INT_SIZE << 3) - 7));
+            $carry = ($high & 0x7F) << ((PHP_INT_SIZE << 3) - 7);
+            $high = ($high >> 7) & ~(0x7F << ((PHP_INT_SIZE << 3) - 7));
+            $low = (($low >> 7) & ~(0x7F << ((PHP_INT_SIZE << 3) - 7)) | $carry);
             $current++;
         }
-        $buffer[$current] = chr($value);
+        $buffer[$current] = chr($low);
         return $current + 1;
     }
 
@@ -130,14 +141,24 @@ class OutputStream
 
     private static function writeLittleEndian64ToArray($value, &$buffer)
     {
-        $buffer[0] = chr($value & 0x000000FF);
-        $buffer[1] = chr(($value >> 8) & 0x000000FF);
-        $buffer[2] = chr(($value >> 16) & 0x000000FF);
-        $buffer[3] = chr(($value >> 24) & 0x000000FF);
-        $buffer[4] = chr(($value >> 32) & 0x000000FF);
-        $buffer[5] = chr(($value >> 40) & 0x000000FF);
-        $buffer[6] = chr(($value >> 48) & 0x000000FF);
-        $buffer[7] = chr(($value >> 56) & 0x000000FF);
+        $high = 0;
+        $low = 0;
+        if (PHP_INT_SIZE == 4) {
+            GPBUtil::divideInt64ToInt32($value, $high, $low);
+        } else {
+            $low = $value & 0xFFFFFFFF;
+            $high = ($value >> 32) & 0xFFFFFFFF;
+        }
+
+        $buffer[0] = chr($low & 0x000000FF);
+        $buffer[1] = chr(($low >> 8) & 0x000000FF);
+        $buffer[2] = chr(($low >> 16) & 0x000000FF);
+        $buffer[3] = chr(($low >> 24) & 0x000000FF);
+        $buffer[4] = chr($high & 0x000000FF);
+        $buffer[5] = chr(($high >> 8) & 0x000000FF);
+        $buffer[6] = chr(($high >> 16) & 0x000000FF);
+        $buffer[7] = chr(($high >> 24) & 0x000000FF);
         return 8;
     }
+
 }

+ 0 - 175
php/src/Google/Protobuf/Internal/Type.php

@@ -1,175 +0,0 @@
-<?php
-
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// 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.
-
-namespace Google\Protobuf\Internal;
-
-class GPBInteger
-{
-    public $high = 0;
-    public $low = 0;
-
-    public function __construct($value = 0)
-    {
-        $this->low = $value & 0xFFFFFFFF;
-        if (PHP_INT_SIZE === 8) {
-            $this->high = ($value >> 32) & 0xFFFFFFFF;
-        }
-    }
-
-    // Return 0 for unsigned integers and 1 for signed integers.
-    protected function sign()
-    {
-        trigger_error("Not implemented", E_ERROR);
-    }
-
-    public function leftShift($count)
-    {
-        if ($count > 63) {
-            $this->low = 0;
-            $this->high = 0;
-            return;
-        }
-        if ($count > 32) {
-            $this->high = $this->low;
-            $this->low = 0;
-            $count -= 32;
-        }
-        $mask = (1 << $count) - 1;
-        $this->high = (($this->high << $count) & 0xFFFFFFFF) |
-                  (($this->low >> (32 - $count)) & $mask);
-        $this->low = ($this->low << $count) & 0xFFFFFFFF;
-
-        $this->high &= 0xFFFFFFFF;
-        $this->low &= 0xFFFFFFFF;
-        return $this;
-    }
-
-    public function rightShift($count)
-    {
-        $sign = (($this->high & 0x80000000) >> 31) & $this->sign();
-        if ($count > 63) {
-            $this->low = -$sign;
-            $this->high = -$sign;
-            return;
-        }
-        if ($count > 32) {
-            $this->low = $this->high;
-            $this->high = -$sign;
-            $count -= 32;
-        }
-        $this->low = (($this->low >> $count) & 0xFFFFFFFF) |
-                 (($this->high << (32 - $count)) & 0xFFFFFFFF);
-        $this->high = (($this->high >> $count) | (-$sign << $count));
-
-        $this->high &= 0xFFFFFFFF;
-        $this->low &= 0xFFFFFFFF;
-
-        return $this;
-    }
-
-    public function bitOr($var)
-    {
-        $this->high |= $var->high;
-        $this->low |= $var->low;
-        return $this;
-    }
-
-    public function bitXor($var)
-    {
-        $this->high ^= $var->high;
-        $this->low ^= $var->low;
-        return $this;
-    }
-
-    public function bitAnd($var)
-    {
-        $this->high &= $var->high;
-        $this->low &= $var->low;
-        return $this;
-    }
-
-    // Even: all zero; Odd: all one.
-    public function oddMask()
-    {
-        $low = (-($this->low & 1)) & 0xFFFFFFFF;
-        $high = $low;
-        return UInt64::newValue($high, $low);
-    }
-
-    public function toInteger()
-    {
-        if (PHP_INT_SIZE === 8) {
-            return ($this->high << 32) | $this->low;
-        } else {
-            return $this->low;
-        }
-    }
-
-    public function copy()
-    {
-        return static::newValue($this->high, $this->low);
-    }
-}
-
-class Uint64 extends GPBInteger
-{
-
-    public static function newValue($high, $low)
-    {
-        $uint64 = new Uint64(0);
-        $uint64->high = $high;
-        $uint64->low = $low;
-        return $uint64;
-    }
-
-    protected function sign()
-    {
-        return 0;
-    }
-}
-
-class Int64 extends GPBInteger
-{
-
-    public static function newValue($high, $low)
-    {
-        $int64 = new Int64(0);
-        $int64->high = $high;
-        $int64->low = $low;
-        return $int64;
-    }
-
-    protected function sign()
-    {
-        return 1;
-    }
-}

+ 21 - 4
php/src/Google/Protobuf/descriptor.php

@@ -215,6 +215,18 @@ class Descriptor
         return $desc;
     }
 }
+
+function addPrefixIfSpecial(
+    $name,
+    $package)
+{
+    if ($name === "Empty" && $package === "google.protobuf") {
+        return "GPBEmpty";
+    } else {
+        return $name;
+    }
+}
+
 function getFullClassName(
     $proto,
     $containing,
@@ -224,7 +236,8 @@ function getFullClassName(
     &$fullname)
 {
     // Full name needs to start with '.'.
-    $message_name_without_package = $proto->getName();
+    $message_name_without_package =
+        addPrefixIfSpecial($proto->getName(), $package);
     if ($containing !== "") {
         $message_name_without_package =
             $containing . "." . $message_name_without_package;
@@ -240,9 +253,13 @@ function getFullClassName(
     $class_name_without_package =
         implode('_', array_map('ucwords',
                                explode('.', $message_name_without_package)));
-    $classname =
-        implode('\\', array_map('ucwords', explode('.', $package))).
-        "\\".$class_name_without_package;
+    if ($package === "") {
+        $classname = $class_name_without_package;
+    } else {
+        $classname =
+            implode('\\', array_map('ucwords', explode('.', $package))).
+            "\\".$class_name_without_package;
+    }
 }
 
 class OneofDescriptor

+ 87 - 35
php/tests/array_test.php

@@ -65,6 +65,17 @@ class RepeatedFieldTest extends PHPUnit_Framework_TestCase
         $this->assertSame(3, $arr[6]);
         $arr [7]= MAX_INT32_STRING;
         $this->assertSame(MAX_INT32, $arr[7]);
+
+        // Test foreach.
+        $arr = new RepeatedField(GPBType::INT32);
+        for ($i = 0; $i < 3; $i++) {
+          $arr []= $i;
+        }
+        $i = 0;
+        foreach ($arr as $val) {
+          $this->assertSame($i++, $val);
+        }
+        $this->assertSame(3, $i);
     }
 
     /**
@@ -225,46 +236,68 @@ class RepeatedFieldTest extends PHPUnit_Framework_TestCase
 
         // Test append.
         $arr []= MAX_INT64;
-        $this->assertSame(MAX_INT64, $arr[0]);
         $arr []= MIN_INT64;
-        $this->assertEquals(MIN_INT64, $arr[1]);
-
         $arr []= 1.1;
-        $this->assertSame(1, $arr[2]);
-
         $arr []= '2';
-        $this->assertSame(2, $arr[3]);
         $arr []= '3.1';
-        $this->assertSame(3, $arr[4]);
         $arr []= MAX_INT64_STRING;
-        $this->assertSame(MAX_INT64, $arr[5]);
         $arr []= MIN_INT64_STRING;
-        $this->assertEquals(MIN_INT64, $arr[6]);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_INT64, $arr[0]);
+            $this->assertSame(MIN_INT64, $arr[1]);
+            $this->assertSame('1', $arr[2]);
+            $this->assertSame('2', $arr[3]);
+            $this->assertSame('3', $arr[4]);
+            $this->assertSame(MAX_INT64_STRING, $arr[5]);
+            $this->assertSame(MIN_INT64_STRING, $arr[6]);
+        } else {
+            $this->assertSame(MAX_INT64, $arr[0]);
+            $this->assertSame(MIN_INT64, $arr[1]);
+            $this->assertSame(1, $arr[2]);
+            $this->assertSame(2, $arr[3]);
+            $this->assertSame(3, $arr[4]);
+            $this->assertSame(MAX_INT64, $arr[5]);
+            $this->assertSame(MIN_INT64, $arr[6]);
+        }
+
 
         $this->assertEquals(7, count($arr));
 
         for ($i = 0; $i < count($arr); $i++) {
             $arr[$i] = 0;
-            $this->assertSame(0, $arr[$i]);
+            if (PHP_INT_SIZE == 4) {
+                $this->assertSame('0', $arr[$i]);
+            } else {
+                $this->assertSame(0, $arr[$i]);
+            }
         }
 
         // Test set.
         $arr [0]= MAX_INT64;
-        $this->assertSame(MAX_INT64, $arr[0]);
         $arr [1]= MIN_INT64;
-        $this->assertEquals(MIN_INT64, $arr[1]);
-
         $arr [2]= 1.1;
-        $this->assertSame(1, $arr[2]);
-
         $arr [3]= '2';
-        $this->assertSame(2, $arr[3]);
         $arr [4]= '3.1';
-        $this->assertSame(3, $arr[4]);
         $arr [5]= MAX_INT64_STRING;
-        $this->assertSame(MAX_INT64, $arr[5]);
         $arr [6]= MIN_INT64_STRING;
-        $this->assertEquals(MIN_INT64, $arr[6]);
+
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_INT64_STRING, $arr[0]);
+            $this->assertSame(MIN_INT64_STRING, $arr[1]);
+            $this->assertSame('1', $arr[2]);
+            $this->assertSame('2', $arr[3]);
+            $this->assertSame('3', $arr[4]);
+            $this->assertSame(MAX_INT64_STRING, $arr[5]);
+            $this->assertEquals(MIN_INT64_STRING, $arr[6]);
+        } else {
+            $this->assertSame(MAX_INT64, $arr[0]);
+            $this->assertSame(MIN_INT64, $arr[1]);
+            $this->assertSame(1, $arr[2]);
+            $this->assertSame(2, $arr[3]);
+            $this->assertSame(3, $arr[4]);
+            $this->assertSame(MAX_INT64, $arr[5]);
+            $this->assertEquals(MIN_INT64, $arr[6]);
+        }
     }
 
     /**
@@ -315,38 +348,57 @@ class RepeatedFieldTest extends PHPUnit_Framework_TestCase
 
         // Test append.
         $arr []= MAX_UINT64;
-        $this->assertEquals(MAX_UINT64, $arr[0]);
-
         $arr []= 1.1;
-        $this->assertSame(1, $arr[1]);
-
         $arr []= '2';
-        $this->assertSame(2, $arr[2]);
         $arr []= '3.1';
-        $this->assertSame(3, $arr[3]);
         $arr []= MAX_UINT64_STRING;
-        $this->assertEquals(MAX_UINT64, $arr[4]);
 
-        $this->assertEquals(5, count($arr));
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_UINT64_STRING, $arr[0]);
+            $this->assertSame('1', $arr[1]);
+            $this->assertSame('2', $arr[2]);
+            $this->assertSame('3', $arr[3]);
+            $this->assertSame(MAX_UINT64_STRING, $arr[4]);
+        } else {
+            $this->assertSame(MAX_UINT64, $arr[0]);
+            $this->assertSame(1, $arr[1]);
+            $this->assertSame(2, $arr[2]);
+            $this->assertSame(3, $arr[3]);
+            $this->assertSame(MAX_UINT64, $arr[4]);
+            $this->assertSame(5, count($arr));
+        }
+
+        $this->assertSame(5, count($arr));
 
         for ($i = 0; $i < count($arr); $i++) {
             $arr[$i] = 0;
-            $this->assertSame(0, $arr[$i]);
+            if (PHP_INT_SIZE == 4) {
+                $this->assertSame('0', $arr[$i]);
+            } else {
+                $this->assertSame(0, $arr[$i]);
+            }
         }
 
         // Test set.
         $arr [0]= MAX_UINT64;
-        $this->assertEquals(MAX_UINT64, $arr[0]);
-
         $arr [1]= 1.1;
-        $this->assertSame(1, $arr[1]);
-
         $arr [2]= '2';
-        $this->assertSame(2, $arr[2]);
         $arr [3]= '3.1';
-        $this->assertSame(3, $arr[3]);
         $arr [4]= MAX_UINT64_STRING;
-        $this->assertEquals(MAX_UINT64, $arr[4]);
+
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_UINT64_STRING, $arr[0]);
+            $this->assertSame('1', $arr[1]);
+            $this->assertSame('2', $arr[2]);
+            $this->assertSame('3', $arr[3]);
+            $this->assertSame(MAX_UINT64_STRING, $arr[4]);
+        } else {
+            $this->assertSame(MAX_UINT64, $arr[0]);
+            $this->assertSame(1, $arr[1]);
+            $this->assertSame(2, $arr[2]);
+            $this->assertSame(3, $arr[3]);
+            $this->assertSame(MAX_UINT64, $arr[4]);
+        }
     }
 
     /**

+ 64 - 10
php/tests/generated_class_test.php

@@ -1,6 +1,7 @@
 <?php
 
 require_once('test.pb.php');
+require_once('test_no_namespace.pb.php');
 require_once('test_util.php');
 
 use Google\Protobuf\Internal\RepeatedField;
@@ -147,17 +148,40 @@ class GeneratedClassTest extends PHPUnit_Framework_TestCase
 
         // Set float.
         $m->setOptionalInt64(1.1);
-        $this->assertSame(1, $m->getOptionalInt64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('1', $m->getOptionalInt64());
+        } else {
+            $this->assertSame(1, $m->getOptionalInt64());
+        }
 
         // Set string.
         $m->setOptionalInt64('2');
-        $this->assertSame(2, $m->getOptionalInt64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('2', $m->getOptionalInt64());
+        } else {
+            $this->assertSame(2, $m->getOptionalInt64());
+        }
+
         $m->setOptionalInt64('3.1');
-        $this->assertSame(3, $m->getOptionalInt64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('3', $m->getOptionalInt64());
+        } else {
+            $this->assertSame(3, $m->getOptionalInt64());
+        }
+
         $m->setOptionalInt64(MAX_INT64_STRING);
-        $this->assertSame(MAX_INT64, $m->getOptionalInt64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_INT64_STRING, $m->getOptionalInt64());
+        } else {
+            $this->assertSame(MAX_INT64, $m->getOptionalInt64());
+        }
+
         $m->setOptionalInt64(MIN_INT64_STRING);
-        $this->assertEquals(MIN_INT64, $m->getOptionalInt64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MIN_INT64_STRING, $m->getOptionalInt64());
+        } else {
+            $this->assertSame(MIN_INT64, $m->getOptionalInt64());
+        }
     }
 
     /**
@@ -188,19 +212,41 @@ class GeneratedClassTest extends PHPUnit_Framework_TestCase
 
         // Set integer.
         $m->setOptionalUint64(MAX_UINT64);
-        $this->assertEquals(MAX_UINT64, $m->getOptionalUint64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_UINT64_STRING, $m->getOptionalUint64());
+        } else {
+            $this->assertSame(MAX_UINT64, $m->getOptionalUint64());
+        }
 
         // Set float.
         $m->setOptionalUint64(1.1);
-        $this->assertSame(1, $m->getOptionalUint64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('1', $m->getOptionalUint64());
+        } else {
+            $this->assertSame(1, $m->getOptionalUint64());
+        }
 
         // Set string.
         $m->setOptionalUint64('2');
-        $this->assertSame(2, $m->getOptionalUint64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('2', $m->getOptionalUint64());
+        } else {
+            $this->assertSame(2, $m->getOptionalUint64());
+        }
+
         $m->setOptionalUint64('3.1');
-        $this->assertSame(3, $m->getOptionalUint64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('3', $m->getOptionalUint64());
+        } else {
+            $this->assertSame(3, $m->getOptionalUint64());
+        }
+
         $m->setOptionalUint64(MAX_UINT64_STRING);
-        $this->assertEquals(MAX_UINT64, $m->getOptionalUint64());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_UINT64_STRING, $m->getOptionalUint64());
+        } else {
+            $this->assertSame(MAX_UINT64, $m->getOptionalUint64());
+        }
     }
 
     /**
@@ -554,4 +600,12 @@ class GeneratedClassTest extends PHPUnit_Framework_TestCase
         $this->assertSame('', $m->getOneofString());
         $this->assertSame(1, $m->getOneofMessage()->getA());
     }
+
+    #########################################################
+    # Test oneof field.
+    #########################################################
+
+    public function testMessageWithoutNamespace() {
+      $m = new NoNameSpace();
+    }
 }

+ 28 - 0
php/tests/google/protobuf/empty.pb.php

@@ -0,0 +1,28 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: google/protobuf/empty.proto
+
+namespace Google\Protobuf;
+
+use Google\Protobuf\Internal\DescriptorPool;
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+class GPBEmpty extends \Google\Protobuf\Internal\Message
+{
+
+}
+
+$pool = DescriptorPool::getGeneratedPool();
+
+$pool->internalAddGeneratedFile(hex2bin(
+    "0ab7010a1b676f6f676c652f70726f746f6275662f656d7074792e70726f" .
+    "746f120f676f6f676c652e70726f746f62756622070a05456d7074794276" .
+    "0a13636f6d2e676f6f676c652e70726f746f627566420a456d7074795072" .
+    "6f746f50015a276769746875622e636f6d2f676f6c616e672f70726f746f" .
+    "6275662f7074797065732f656d707479f80101a20203475042aa021e476f" .
+    "6f676c652e50726f746f6275662e57656c6c4b6e6f776e54797065736206" .
+    "70726f746f33"
+));
+

+ 44 - 12
php/tests/map_field_test.php

@@ -205,9 +205,14 @@ class MapFieldTest extends PHPUnit_Framework_TestCase {
 
         // Test integer argument.
         $arr[MAX_INT64] = MAX_INT64;
-        $this->assertSame(MAX_INT64, $arr[MAX_INT64]);
         $arr[MIN_INT64] = MIN_INT64;
-        $this->assertEquals(MIN_INT64, $arr[MIN_INT64]);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_INT64_STRING, $arr[MAX_INT64_STRING]);
+            $this->assertSame(MIN_INT64_STRING, $arr[MIN_INT64_STRING]);
+        } else {
+            $this->assertSame(MAX_INT64, $arr[MAX_INT64]);
+            $this->assertSame(MIN_INT64, $arr[MIN_INT64]);
+        }
         $this->assertEquals(2, count($arr));
         unset($arr[MAX_INT64]);
         unset($arr[MIN_INT64]);
@@ -215,20 +220,31 @@ class MapFieldTest extends PHPUnit_Framework_TestCase {
 
         // Test float argument.
         $arr[1.1] = 1.1;
-        $this->assertSame(1, $arr[1]);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('1', $arr['1']);
+        } else {
+            $this->assertSame(1, $arr[1]);
+        }
         $this->assertEquals(1, count($arr));
         unset($arr[1.1]);
         $this->assertEquals(0, count($arr));
 
         // Test string argument.
         $arr['2'] = '2';
-        $this->assertSame(2, $arr[2]);
         $arr['3.1'] = '3.1';
-        $this->assertSame(3, $arr[3]);
         $arr[MAX_INT64_STRING] = MAX_INT64_STRING;
-        $this->assertSame(MAX_INT64, $arr[MAX_INT64]);
         $arr[MIN_INT64_STRING] = MIN_INT64_STRING;
-        $this->assertEquals(MIN_INT64, $arr[MIN_INT64]);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('2', $arr['2']);
+            $this->assertSame('3', $arr['3']);
+            $this->assertSame(MAX_INT64_STRING, $arr[MAX_INT64_STRING]);
+            $this->assertSame(MIN_INT64_STRING, $arr[MIN_INT64_STRING]);
+        } else {
+            $this->assertSame(2, $arr[2]);
+            $this->assertSame(3, $arr[3]);
+            $this->assertSame(MAX_INT64, $arr[MAX_INT64]);
+            $this->assertSame(MIN_INT64, $arr[MIN_INT64]);
+        }
         $this->assertEquals(4, count($arr));
         unset($arr['2']);
         unset($arr['3.1']);
@@ -282,25 +298,41 @@ class MapFieldTest extends PHPUnit_Framework_TestCase {
 
         // Test integer argument.
         $arr[MAX_UINT64] = MAX_UINT64;
-        $this->assertEquals(MAX_UINT64, $arr[MAX_UINT64]);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame(MAX_UINT64_STRING, $arr[MAX_UINT64_STRING]);
+        } else {
+            $this->assertSame(MAX_UINT64, $arr[MAX_UINT64]);
+        }
         $this->assertEquals(1, count($arr));
         unset($arr[MAX_UINT64]);
         $this->assertEquals(0, count($arr));
 
         // Test float argument.
         $arr[1.1] = 1.1;
-        $this->assertSame(1, $arr[1]);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('1', $arr['1']);
+        } else {
+            $this->assertSame(1, $arr[1]);
+        }
         $this->assertEquals(1, count($arr));
         unset($arr[1.1]);
         $this->assertEquals(0, count($arr));
 
         // Test string argument.
         $arr['2'] = '2';
-        $this->assertSame(2, $arr[2]);
         $arr['3.1'] = '3.1';
-        $this->assertSame(3, $arr[3]);
         $arr[MAX_UINT64_STRING] = MAX_UINT64_STRING;
-        $this->assertEquals(MAX_UINT64, $arr[MAX_UINT64]);
+
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('2', $arr['2']);
+            $this->assertSame('3', $arr['3']);
+            $this->assertSame(MAX_UINT64_STRING, $arr[MAX_UINT64_STRING]);
+        } else {
+            $this->assertSame(2, $arr[2]);
+            $this->assertSame(3, $arr[3]);
+            $this->assertSame(MAX_UINT64, $arr[MAX_UINT64]);
+        }
+
         $this->assertEquals(3, count($arr));
         unset($arr['2']);
         unset($arr['3.1']);

+ 93 - 55
php/tests/php_implementation_test.php

@@ -9,14 +9,10 @@ use Foo\TestMessage_Sub;
 use Foo\TestPackedMessage;
 use Google\Protobuf\Internal\InputStream;
 use Google\Protobuf\Internal\FileDescriptorSet;
-use Google\Protobuf\Internal\GPBUtil;
-use Google\Protobuf\Internal\Int64;
-use Google\Protobuf\Internal\Uint64;
 use Google\Protobuf\Internal\GPBLabel;
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\OutputStream;
-use Google\Protobuf\Internal\RepeatedField;
 
 class ImplementationTest extends TestBase
 {
@@ -68,17 +64,17 @@ class ImplementationTest extends TestBase
         // Positive number.
         $input = new InputStream(hex2bin("01"));
         GPBWire::readInt64($input, $value);
-        $this->assertSame(1, $value->toInteger());
+        $this->assertEquals(1, $value);
 
         // Negative number.
         $input = new InputStream(hex2bin("ffffffffffffffffff01"));
         GPBWire::readInt64($input, $value);
-        $this->assertSame(-1, $value->toInteger());
+        $this->assertEquals(-1, $value);
 
         // Discard overflow bits.
         $input = new InputStream(hex2bin("ffffffffffffffffff0f"));
         GPBWire::readInt64($input, $value);
-        $this->assertSame(-1, $value->toInteger());
+        $this->assertEquals(-1, $value);
     }
 
     public function testReadUint64()
@@ -88,17 +84,17 @@ class ImplementationTest extends TestBase
         // Positive number.
         $input = new InputStream(hex2bin("01"));
         GPBWire::readUint64($input, $value);
-        $this->assertSame(1, $value->toInteger());
+        $this->assertEquals(1, $value);
 
         // Negative number.
         $input = new InputStream(hex2bin("FFFFFFFFFFFFFFFFFF01"));
         GPBWire::readUint64($input, $value);
-        $this->assertSame(-1, $value->toInteger());
+        $this->assertEquals(-1, $value);
 
         // Discard overflow bits.
         $input = new InputStream(hex2bin("FFFFFFFFFFFFFFFFFF0F"));
         GPBWire::readUint64($input, $value);
-        $this->assertSame(-1, $value->toInteger());
+        $this->assertEquals(-1, $value);
     }
 
     public function testReadSint32()
@@ -124,15 +120,15 @@ class ImplementationTest extends TestBase
 
         $input = new InputStream(hex2bin("00"));
         GPBWire::readSint64($input, $value);
-        $this->assertEquals(GPBUtil::Int64(0), $value);
+        $this->assertEquals(0, $value);
 
         $input = new InputStream(hex2bin("01"));
         GPBWire::readSint64($input, $value);
-        $this->assertEquals(GPBUtil::Int64(-1), $value);
+        $this->assertEquals(-1, $value);
 
         $input = new InputStream(hex2bin("02"));
         GPBWire::readSint64($input, $value);
-        $this->assertEquals(GPBUtil::Int64(1), $value);
+        $this->assertEquals(1, $value);
     }
 
     public function testReadFixed32()
@@ -148,7 +144,11 @@ class ImplementationTest extends TestBase
         $value = null;
         $input = new InputStream(hex2bin("1234567812345678"));
         GPBWire::readFixed64($input, $value);
-        $this->assertEquals(Uint64::newValue(0x78563412, 0x78563412), $value);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame("8671175386481439762", $value);
+        } else {
+            $this->assertSame(0x7856341278563412, $value);
+        }
     }
 
     public function testReadSfixed32()
@@ -193,7 +193,11 @@ class ImplementationTest extends TestBase
         $value = null;
         $input = new InputStream(hex2bin("1234567812345678"));
         GPBWire::readSfixed64($input, $value);
-        $this->assertEquals(Int64::newValue(0x78563412, 0x78563412), $value);
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame("8671175386481439762", $value);
+        } else {
+            $this->assertSame(0x7856341278563412, $value);
+        }
     }
 
     public function testZigZagEncodeDecode()
@@ -214,43 +218,65 @@ class ImplementationTest extends TestBase
         $this->assertSame(0x3FFFFFFF,  GPBWire::zigZagDecode32(0x7FFFFFFE));
         $this->assertSame(-1073741824, GPBWire::zigZagDecode32(0x7FFFFFFF));
         $this->assertSame(0x7FFFFFFF,  GPBWire::zigZagDecode32(0xFFFFFFFE));
-        $this->assertSame(-2147483648, GPBWire::zigZagDecode32(0xFFFFFFFF));
-
-        $this->assertEquals(GPBUtil::Uint64(0),
-                        GPBWire::zigZagEncode64(GPBUtil::Int64(0)));
-        $this->assertEquals(GPBUtil::Uint64(1),
-                        GPBWire::zigZagEncode64(GPBUtil::Int64(-1)));
-        $this->assertEquals(GPBUtil::Uint64(2),
-                        GPBWire::zigZagEncode64(GPBUtil::Int64(1)));
-        $this->assertEquals(GPBUtil::Uint64(3),
-                        GPBWire::zigZagEncode64(GPBUtil::Int64(-2)));
-        $this->assertEquals(
-        GPBUtil::Uint64(0x000000007FFFFFFE),
-        GPBWire::zigZagEncode64(GPBUtil::Int64(0x000000003FFFFFFF)));
-        $this->assertEquals(
-        GPBUtil::Uint64(0x000000007FFFFFFF),
-        GPBWire::zigZagEncode64(GPBUtil::Int64(0xFFFFFFFFC0000000)));
-        $this->assertEquals(
-        GPBUtil::Uint64(0x00000000FFFFFFFE),
-        GPBWire::zigZagEncode64(GPBUtil::Int64(0x000000007FFFFFFF)));
-        $this->assertEquals(
-        GPBUtil::Uint64(0x00000000FFFFFFFF),
-        GPBWire::zigZagEncode64(GPBUtil::Int64(0xFFFFFFFF80000000)));
-        $this->assertEquals(
-        Uint64::newValue(4294967295, 4294967294),
-        GPBWire::zigZagEncode64(GPBUtil::Int64(0x7FFFFFFFFFFFFFFF)));
-        $this->assertEquals(
-        Uint64::newValue(4294967295, 4294967295),
-        GPBWire::zigZagEncode64(GPBUtil::Int64(0x8000000000000000)));
-
-        $this->assertEquals(GPBUtil::Int64(0),
-                        GPBWire::zigZagDecode64(GPBUtil::Uint64(0)));
-        $this->assertEquals(GPBUtil::Int64(-1),
-                        GPBWire::zigZagDecode64(GPBUtil::Uint64(1)));
-        $this->assertEquals(GPBUtil::Int64(1),
-                        GPBWire::zigZagDecode64(GPBUtil::Uint64(2)));
-        $this->assertEquals(GPBUtil::Int64(-2),
-                        GPBWire::zigZagDecode64(GPBUtil::Uint64(3)));
+        $this->assertSame((int)-2147483648,GPBWire::zigZagDecode32(0xFFFFFFFF));
+
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('0', GPBWire::zigZagEncode64(0));
+            $this->assertSame('1', GPBWire::zigZagEncode64(-1));
+            $this->assertSame('2', GPBWire::zigZagEncode64(1));
+            $this->assertSame('3', GPBWire::zigZagEncode64(-2));
+            $this->assertSame(
+                '2147483646',  // 0x7FFFFFE
+                GPBWire::zigZagEncode64(0x3FFFFFFF));
+            $this->assertSame(
+                '2147483647',  // 0x7FFFFFF
+                GPBWire::zigZagEncode64(-1073741824));  // 0xFFFFFFFFC0000000
+            $this->assertSame(
+                '4294967294',                           // 0xFFFFFFFE
+                GPBWire::zigZagEncode64(2147483647));   // 0x7FFFFFFF
+            $this->assertSame(
+                '4294967295',                           // 0xFFFFFFFF
+                GPBWire::zigZagEncode64(-2147483648));  // 0xFFFFFFFF80000000
+            $this->assertSame(
+                '18446744073709551614',  // 0xFFFFFFFFFFFFFFFE
+                                         // 0x7FFFFFFFFFFFFFFF
+                GPBWire::zigZagEncode64("9223372036854775807"));
+            $this->assertSame(
+                '18446744073709551615',  // 0xFFFFFFFFFFFFFFFF
+                                         // 0x8000000000000000
+                GPBWire::zigZagEncode64("-9223372036854775808"));
+
+            $this->assertSame('0', GPBWire::zigZagDecode64(0));
+            $this->assertSame('-1', GPBWire::zigZagDecode64(1));
+            $this->assertSame('1', GPBWire::zigZagDecode64(2));
+            $this->assertSame('-2', GPBWire::zigZagDecode64(3));
+        } else {
+            $this->assertSame(0, GPBWire::zigZagEncode64(0));
+            $this->assertSame(1, GPBWire::zigZagEncode64(-1));
+            $this->assertSame(2, GPBWire::zigZagEncode64(1));
+            $this->assertSame(3, GPBWire::zigZagEncode64(-2));
+            $this->assertSame(0x7FFFFFFE, GPBWire::zigZagEncode64(0x3FFFFFFF));
+            $this->assertSame(
+                0x7FFFFFFF,
+                GPBWire::zigZagEncode64(0xFFFFFFFFC0000000));
+            $this->assertSame(
+                0xFFFFFFFE,
+                GPBWire::zigZagEncode64(0x7FFFFFFF));
+            $this->assertSame(
+                0xFFFFFFFF,
+                GPBWire::zigZagEncode64(0xFFFFFFFF80000000));
+            $this->assertSame(
+                -2,  // 0xFFFFFFFFFFFFFFFE
+                GPBWire::zigZagEncode64(0x7FFFFFFFFFFFFFFF));
+            $this->assertSame(
+                -1,  // 0xFFFFFFFFFFFFFFFF
+                GPBWire::zigZagEncode64(0x8000000000000000));
+
+            $this->assertSame(0, GPBWire::zigZagDecode64(0));
+            $this->assertSame(-1, GPBWire::zigZagDecode64(1));
+            $this->assertSame(1, GPBWire::zigZagDecode64(2));
+            $this->assertSame(-2, GPBWire::zigZagDecode64(3));
+        }
 
         // Round trip
         $this->assertSame(0, GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(0)));
@@ -319,15 +345,27 @@ class ImplementationTest extends TestBase
         // Normal case.
         $input = new InputStream(hex2bin('808001'));
         $this->assertTrue($input->readVarint64($var));
-        $this->assertSame(16384, $var->toInteger());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('16384', $var);
+        } else {
+            $this->assertSame(16384, $var);
+        }
         $this->assertFalse($input->readVarint64($var));
 
         // Read two varint.
         $input = new InputStream(hex2bin('808001808002'));
         $this->assertTrue($input->readVarint64($var));
-        $this->assertSame(16384, $var->toInteger());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('16384', $var);
+        } else {
+            $this->assertSame(16384, $var);
+        }
         $this->assertTrue($input->readVarint64($var));
-        $this->assertSame(32768, $var->toInteger());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('32768', $var);
+        } else {
+            $this->assertSame(32768, $var);
+        }
         $this->assertFalse($input->readVarint64($var));
     }
 

+ 3 - 2
php/tests/test.sh

@@ -7,10 +7,11 @@
 pushd ../ext/google/protobuf/
 make clean
 set -e
-phpize && ./configure --enable-debug CFLAGS='-g -O0' && make
+# Add following in configure for debug: --enable-debug CFLAGS='-g -O0'
+phpize && ./configure && make
 popd
 
-tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php )
+tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php well_known_test.php )
 
 for t in "${tests[@]}"
 do

+ 26 - 12
php/tests/test_base.php

@@ -13,22 +13,28 @@ class TestBase extends PHPUnit_Framework_TestCase
 
     public function expectFields(TestMessage $m)
     {
-        $this->assertSame(-42,  $m->getOptionalInt32());
-        $this->assertSame(42,   $m->getOptionalUint32());
-        $this->assertSame(-43,  $m->getOptionalInt64());
-        $this->assertSame(43,   $m->getOptionalUint64());
         $this->assertSame(-44,  $m->getOptionalSint32());
-        $this->assertSame(-45,  $m->getOptionalSint64());
         $this->assertSame(46,   $m->getOptionalFixed32());
-        $this->assertSame(47,   $m->getOptionalFixed64());
         $this->assertSame(-46,  $m->getOptionalSfixed32());
-        $this->assertSame(-47,  $m->getOptionalSfixed64());
         $this->assertSame(1.5,  $m->getOptionalFloat());
         $this->assertSame(1.6,  $m->getOptionalDouble());
         $this->assertSame(true, $m->getOptionalBool());
         $this->assertSame('a',  $m->getOptionalString());
         $this->assertSame('b',  $m->getOptionalBytes());
         $this->assertSame(33,   $m->getOptionalMessage()->getA());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame('-43',  $m->getOptionalInt64());
+            $this->assertSame('43',   $m->getOptionalUint64());
+            $this->assertSame('-45',  $m->getOptionalSint64());
+            $this->assertSame('47',   $m->getOptionalFixed64());
+            $this->assertSame('-47',  $m->getOptionalSfixed64());
+        } else {
+            $this->assertSame(-43,  $m->getOptionalInt64());
+            $this->assertSame(43,   $m->getOptionalUint64());
+            $this->assertSame(-45,  $m->getOptionalSint64());
+            $this->assertSame(47,   $m->getOptionalFixed64());
+            $this->assertSame(-47,  $m->getOptionalSfixed64());
+        }
 
         $this->assertEquals(-42,  $m->getRepeatedInt32()[0]);
         $this->assertEquals(42,   $m->getRepeatedUint32()[0]);
@@ -69,20 +75,28 @@ class TestBase extends PHPUnit_Framework_TestCase
     {
         $this->assertSame(0,   $m->getOptionalInt32());
         $this->assertSame(0,   $m->getOptionalUint32());
-        $this->assertSame(0,   $m->getOptionalInt64());
-        $this->assertSame(0,   $m->getOptionalUint64());
         $this->assertSame(0,   $m->getOptionalSint32());
-        $this->assertSame(0,   $m->getOptionalSint64());
         $this->assertSame(0,   $m->getOptionalFixed32());
-        $this->assertSame(0,   $m->getOptionalFixed64());
         $this->assertSame(0,   $m->getOptionalSfixed32());
-        $this->assertSame(0,   $m->getOptionalSfixed64());
         $this->assertSame(0.0, $m->getOptionalFloat());
         $this->assertSame(0.0, $m->getOptionalDouble());
         $this->assertSame(false, $m->getOptionalBool());
         $this->assertSame('',  $m->getOptionalString());
         $this->assertSame('',  $m->getOptionalBytes());
         $this->assertNull($m->getOptionalMessage());
+        if (PHP_INT_SIZE == 4) {
+            $this->assertSame("0", $m->getOptionalInt64());
+            $this->assertSame("0", $m->getOptionalUint64());
+            $this->assertSame("0", $m->getOptionalSint64());
+            $this->assertSame("0", $m->getOptionalFixed64());
+            $this->assertSame("0", $m->getOptionalSfixed64());
+        } else {
+            $this->assertSame(0, $m->getOptionalInt64());
+            $this->assertSame(0, $m->getOptionalUint64());
+            $this->assertSame(0, $m->getOptionalSint64());
+            $this->assertSame(0, $m->getOptionalFixed64());
+            $this->assertSame(0, $m->getOptionalSfixed64());
+        }
     }
 
   // This test is to avoid the warning of no test by php unit.

+ 34 - 0
php/tests/test_no_namespace.pb.php

@@ -0,0 +1,34 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: test_no_namespace.proto
+
+use Google\Protobuf\Internal\DescriptorPool;
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+class NoNameSpace extends \Google\Protobuf\Internal\Message
+{
+    private $a = 0;
+
+    public function getA()
+    {
+        return $this->a;
+    }
+
+    public function setA($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->a = $var;
+    }
+
+}
+
+$pool = DescriptorPool::getGeneratedPool();
+
+$pool->internalAddGeneratedFile(hex2bin(
+    "0a3b0a17746573745f6e6f5f6e616d6573706163652e70726f746f22180a" .
+    "0b4e6f4e616d65537061636512090a0161180120012805620670726f746f" .
+    "33"
+));
+

+ 5 - 0
php/tests/test_no_namespace.proto

@@ -0,0 +1,5 @@
+syntax = "proto3";
+
+message NoNameSpace {
+  int32 a = 1;
+}

+ 83 - 38
php/tests/test_util.php

@@ -20,7 +20,7 @@ define('MAX_INT32', 2147483647);
 define('MAX_INT32_FLOAT', 2147483647.0);
 define('MAX_INT32_STRING', '2147483647');
 
-define('MIN_INT32', -2147483648);
+define('MIN_INT32', (int)-2147483648);
 define('MIN_INT32_FLOAT', -2147483648.0);
 define('MIN_INT32_STRING', '-2147483648');
 
@@ -28,23 +28,24 @@ define('MAX_UINT32', 4294967295);
 define('MAX_UINT32_FLOAT', 4294967295.0);
 define('MAX_UINT32_STRING', '4294967295');
 
-define('MIN_UINT32', -2147483648);
+define('MIN_UINT32', (int)-2147483648);
 define('MIN_UINT32_FLOAT', -2147483648.0);
 define('MIN_UINT32_STRING', '-2147483648');
 
-define('MAX_INT64', 9223372036854775807);
-define('MAX_INT64_STRING', '9223372036854775807');
+define('MAX_INT64_STRING',  '9223372036854775807');
+define('MIN_INT64_STRING',  '-9223372036854775808');
+define('MAX_UINT64_STRING', '-9223372036854775808');
 
-define('MIN_INT64_STRING', '-9223372036854775808');
 if (PHP_INT_SIZE === 8) {
-    define('MIN_INT64', -9223372036854775808);
+    define('MAX_INT64',  (int)9223372036854775807);
+    define('MIN_INT64',  (int)-9223372036854775808);
+    define('MAX_UINT64', (int)-9223372036854775808);
 } else {
+    define('MAX_INT64', MAX_INT64_STRING);
     define('MIN_INT64', MIN_INT64_STRING);
+    define('MAX_UINT64', MAX_UINT64_STRING);
 }
 
-define('MAX_UINT64_STRING', '-9223372036854775808');
-define('MAX_UINT64', MAX_UINT64_STRING);
-
 class TestUtil
 {
 
@@ -129,16 +130,24 @@ class TestUtil
 
     public static function assertTestMessage(TestMessage $m)
     {
+        if (PHP_INT_SIZE == 4) {
+            assert('-43' === $m->getOptionalInt64());
+            assert('43'  === $m->getOptionalUint64());
+            assert('-45' === $m->getOptionalSint64());
+            assert('47'  === $m->getOptionalFixed64());
+            assert('-47' === $m->getOptionalSfixed64());
+        } else {
+            assert(-43 === $m->getOptionalInt64());
+            assert(43  === $m->getOptionalUint64());
+            assert(-45 === $m->getOptionalSint64());
+            assert(47  === $m->getOptionalFixed64());
+            assert(-47 === $m->getOptionalSfixed64());
+        }
         assert(-42 === $m->getOptionalInt32());
         assert(42  === $m->getOptionalUint32());
-        assert(-43 === $m->getOptionalInt64());
-        assert(43  === $m->getOptionalUint64());
         assert(-44 === $m->getOptionalSint32());
-        assert(-45 === $m->getOptionalSint64());
         assert(46  === $m->getOptionalFixed32());
-        assert(47  === $m->getOptionalFixed64());
         assert(-46 === $m->getOptionalSfixed32());
-        assert(-47 === $m->getOptionalSfixed64());
         assert(1.5 === $m->getOptionalFloat());
         assert(1.6 === $m->getOptionalDouble());
         assert(true=== $m->getOptionalBool());
@@ -147,16 +156,24 @@ class TestUtil
         assert(TestEnum::ONE === $m->getOptionalEnum());
         assert(33  === $m->getOptionalMessage()->getA());
 
+        if (PHP_INT_SIZE == 4) {
+            assert('-43' === $m->getRepeatedInt64()[0]);
+            assert('43'  === $m->getRepeatedUint64()[0]);
+            assert('-45' === $m->getRepeatedSint64()[0]);
+            assert('47'  === $m->getRepeatedFixed64()[0]);
+            assert('-47' === $m->getRepeatedSfixed64()[0]);
+        } else {
+            assert(-43 === $m->getRepeatedInt64()[0]);
+            assert(43  === $m->getRepeatedUint64()[0]);
+            assert(-45 === $m->getRepeatedSint64()[0]);
+            assert(47  === $m->getRepeatedFixed64()[0]);
+            assert(-47 === $m->getRepeatedSfixed64()[0]);
+        }
         assert(-42 === $m->getRepeatedInt32()[0]);
         assert(42  === $m->getRepeatedUint32()[0]);
-        assert(-43 === $m->getRepeatedInt64()[0]);
-        assert(43  === $m->getRepeatedUint64()[0]);
         assert(-44 === $m->getRepeatedSint32()[0]);
-        assert(-45 === $m->getRepeatedSint64()[0]);
         assert(46  === $m->getRepeatedFixed32()[0]);
-        assert(47  === $m->getRepeatedFixed64()[0]);
         assert(-46 === $m->getRepeatedSfixed32()[0]);
-        assert(-47 === $m->getRepeatedSfixed64()[0]);
         assert(1.5 === $m->getRepeatedFloat()[0]);
         assert(1.6 === $m->getRepeatedDouble()[0]);
         assert(true=== $m->getRepeatedBool()[0]);
@@ -165,16 +182,24 @@ class TestUtil
         assert(TestEnum::ZERO === $m->getRepeatedEnum()[0]);
         assert(34  === $m->getRepeatedMessage()[0]->getA());
 
+        if (PHP_INT_SIZE == 4) {
+            assert('-53' === $m->getRepeatedInt64()[1]);
+            assert('53'  === $m->getRepeatedUint64()[1]);
+            assert('-55' === $m->getRepeatedSint64()[1]);
+            assert('57'  === $m->getRepeatedFixed64()[1]);
+            assert('-57' === $m->getRepeatedSfixed64()[1]);
+        } else {
+            assert(-53 === $m->getRepeatedInt64()[1]);
+            assert(53  === $m->getRepeatedUint64()[1]);
+            assert(-55 === $m->getRepeatedSint64()[1]);
+            assert(57  === $m->getRepeatedFixed64()[1]);
+            assert(-57 === $m->getRepeatedSfixed64()[1]);
+        }
         assert(-52 === $m->getRepeatedInt32()[1]);
         assert(52  === $m->getRepeatedUint32()[1]);
-        assert(-53 === $m->getRepeatedInt64()[1]);
-        assert(53  === $m->getRepeatedUint64()[1]);
         assert(-54 === $m->getRepeatedSint32()[1]);
-        assert(-55 === $m->getRepeatedSint64()[1]);
         assert(56  === $m->getRepeatedFixed32()[1]);
-        assert(57  === $m->getRepeatedFixed64()[1]);
         assert(-56 === $m->getRepeatedSfixed32()[1]);
-        assert(-57 === $m->getRepeatedSfixed64()[1]);
         assert(2.5 === $m->getRepeatedFloat()[1]);
         assert(2.6 === $m->getRepeatedDouble()[1]);
         assert(false === $m->getRepeatedBool()[1]);
@@ -183,14 +208,21 @@ class TestUtil
         assert(TestEnum::ONE === $m->getRepeatedEnum()[1]);
         assert(35  === $m->getRepeatedMessage()[1]->getA());
 
+        if (PHP_INT_SIZE == 4) {
+            assert('-63' === $m->getMapInt64Int64()['-63']);
+            assert('63'  === $m->getMapUint64Uint64()['63']);
+            assert('-65' === $m->getMapSint64Sint64()['-65']);
+            assert('67'  === $m->getMapFixed64Fixed64()['67']);
+        } else {
+            assert(-63 === $m->getMapInt64Int64()[-63]);
+            assert(63  === $m->getMapUint64Uint64()[63]);
+            assert(-65 === $m->getMapSint64Sint64()[-65]);
+            assert(67  === $m->getMapFixed64Fixed64()[67]);
+        }
         assert(-62 === $m->getMapInt32Int32()[-62]);
-        assert(-63 === $m->getMapInt64Int64()[-63]);
         assert(62  === $m->getMapUint32Uint32()[62]);
-        assert(63  === $m->getMapUint64Uint64()[63]);
         assert(-64 === $m->getMapSint32Sint32()[-64]);
-        assert(-65 === $m->getMapSint64Sint64()[-65]);
         assert(66  === $m->getMapFixed32Fixed32()[66]);
-        assert(67  === $m->getMapFixed64Fixed64()[67]);
         assert(3.5 === $m->getMapInt32Float()[1]);
         assert(3.6 === $m->getMapInt32Double()[1]);
         assert(true === $m->getMapBoolBool()[true]);
@@ -325,24 +357,14 @@ class TestUtil
 
         assert(-42 === $m->getRepeatedInt32()[0]);
         assert(-52 === $m->getRepeatedInt32()[1]);
-        assert(-43 === $m->getRepeatedInt64()[0]);
-        assert(-53 === $m->getRepeatedInt64()[1]);
         assert(42  === $m->getRepeatedUint32()[0]);
         assert(52  === $m->getRepeatedUint32()[1]);
-        assert(43  === $m->getRepeatedUint64()[0]);
-        assert(53  === $m->getRepeatedUint64()[1]);
         assert(-44 === $m->getRepeatedSint32()[0]);
         assert(-54 === $m->getRepeatedSint32()[1]);
-        assert(-45 === $m->getRepeatedSint64()[0]);
-        assert(-55 === $m->getRepeatedSint64()[1]);
         assert(46  === $m->getRepeatedFixed32()[0]);
         assert(56  === $m->getRepeatedFixed32()[1]);
-        assert(47  === $m->getRepeatedFixed64()[0]);
-        assert(57  === $m->getRepeatedFixed64()[1]);
         assert(-46 === $m->getRepeatedSfixed32()[0]);
         assert(-56 === $m->getRepeatedSfixed32()[1]);
-        assert(-47 === $m->getRepeatedSfixed64()[0]);
-        assert(-57 === $m->getRepeatedSfixed64()[1]);
         assert(1.5 === $m->getRepeatedFloat()[0]);
         assert(2.5 === $m->getRepeatedFloat()[1]);
         assert(1.6 === $m->getRepeatedDouble()[0]);
@@ -351,6 +373,29 @@ class TestUtil
         assert(false === $m->getRepeatedBool()[1]);
         assert(TestEnum::ONE  === $m->getRepeatedEnum()[0]);
         assert(TestEnum::ZERO === $m->getRepeatedEnum()[1]);
+        if (PHP_INT_SIZE == 4) {
+            assert('-43' === $m->getRepeatedInt64()[0]);
+            assert('-53' === $m->getRepeatedInt64()[1]);
+            assert('43'  === $m->getRepeatedUint64()[0]);
+            assert('53'  === $m->getRepeatedUint64()[1]);
+            assert('-45' === $m->getRepeatedSint64()[0]);
+            assert('-55' === $m->getRepeatedSint64()[1]);
+            assert('47'  === $m->getRepeatedFixed64()[0]);
+            assert('57'  === $m->getRepeatedFixed64()[1]);
+            assert('-47' === $m->getRepeatedSfixed64()[0]);
+            assert('-57' === $m->getRepeatedSfixed64()[1]);
+        } else {
+            assert(-43 === $m->getRepeatedInt64()[0]);
+            assert(-53 === $m->getRepeatedInt64()[1]);
+            assert(43  === $m->getRepeatedUint64()[0]);
+            assert(53  === $m->getRepeatedUint64()[1]);
+            assert(-45 === $m->getRepeatedSint64()[0]);
+            assert(-55 === $m->getRepeatedSint64()[1]);
+            assert(47  === $m->getRepeatedFixed64()[0]);
+            assert(57  === $m->getRepeatedFixed64()[1]);
+            assert(-47 === $m->getRepeatedSfixed64()[0]);
+            assert(-57 === $m->getRepeatedSfixed64()[1]);
+        }
     }
 
     public static function getGoldenTestPackedMessage()

+ 13 - 0
php/tests/well_known_test.php

@@ -0,0 +1,13 @@
+<?php
+
+require_once("google/protobuf/empty.pb.php");
+
+use Google\Protobuf\GPBEmpty;
+
+class WellKnownTest extends PHPUnit_Framework_TestCase {
+
+    public function testNone() {
+      $msg = new GPBEmpty();
+    }
+
+}

+ 1 - 0
phpunit.xml

@@ -8,6 +8,7 @@
       <file>php/tests/encode_decode_test.php</file>
       <file>php/tests/generated_class_test.php</file>
       <file>php/tests/map_field_test.php</file>
+      <file>php/tests/well_known_test.php</file>
     </testsuite>
   </testsuites>
 </phpunit>

+ 17 - 7
protobuf.bzl

@@ -13,14 +13,21 @@ def _GenDir(ctx):
     return _GetPath(ctx, ctx.attr.includes[0])
   return _GetPath(ctx, ctx.label.package + '/' + ctx.attr.includes[0])
 
-def _CcOuts(srcs, use_grpc_plugin=False):
-  ret = [s[:-len(".proto")] + ".pb.h" for s in srcs] + \
-        [s[:-len(".proto")] + ".pb.cc" for s in srcs]
+def _CcHdrs(srcs, use_grpc_plugin=False):
+  ret = [s[:-len(".proto")] + ".pb.h" for s in srcs]
+  if use_grpc_plugin:
+    ret += [s[:-len(".proto")] + ".grpc.pb.h" for s in srcs]
+  return ret
+
+def _CcSrcs(srcs, use_grpc_plugin=False):
+  ret = [s[:-len(".proto")] + ".pb.cc" for s in srcs]
   if use_grpc_plugin:
-    ret += [s[:-len(".proto")] + ".grpc.pb.h" for s in srcs] + \
-           [s[:-len(".proto")] + ".grpc.pb.cc" for s in srcs]
+    ret += [s[:-len(".proto")] + ".grpc.pb.cc" for s in srcs]
   return ret
 
+def _CcOuts(srcs, use_grpc_plugin=False):
+  return _CcHdrs(srcs, use_grpc_plugin) + _CcSrcs(srcs, use_grpc_plugin)
+
 def _PyOuts(srcs):
   return [s[:-len(".proto")] + "_pb2.py" for s in srcs]
 
@@ -201,7 +208,9 @@ def cc_proto_library(
   if use_grpc_plugin:
     grpc_cpp_plugin = "//external:grpc_cpp_plugin"
 
-  outs = _CcOuts(srcs, use_grpc_plugin)
+  gen_srcs = _CcSrcs(srcs, use_grpc_plugin)
+  gen_hdrs = _CcHdrs(srcs, use_grpc_plugin)
+  outs = gen_srcs + gen_hdrs
 
   proto_gen(
       name=name + "_genproto",
@@ -223,7 +232,8 @@ def cc_proto_library(
 
   native.cc_library(
       name=name,
-      srcs=outs,
+      srcs=gen_srcs,
+      hdrs=gen_hdrs,
       deps=cc_libs + deps,
       includes=includes,
       **kargs)

+ 1 - 1
python/README.md

@@ -92,7 +92,7 @@ Installation
    error:  "sem_init: Resource temporarily unavailable".  This appears
    to be a bug either in Cygwin or in Python:
      http://www.cygwin.com/ml/cygwin/2005-07/msg01378.html
-   We do not know if or when it might me fixed.  We also do not know
+   We do not know if or when it might be fixed.  We also do not know
    how likely it is that this bug will affect users in practice.
 
 5) Install:

+ 4 - 0
python/google/protobuf/pyext/message.cc

@@ -1994,7 +1994,11 @@ static PyObject* CopyFrom(CMessage* self, PyObject* arg) {
 // get OOM errors. The protobuf APIs do not provide any tools for processing
 // protobufs in chunks.  If you have protos this big you should break them up if
 // it is at all convenient to do so.
+#ifdef PROTOBUF_PYTHON_ALLOW_OVERSIZE_PROTOS
+static bool allow_oversize_protos = true;
+#else
 static bool allow_oversize_protos = false;
+#endif
 
 // Provide a method in the module to set allow_oversize_protos to a boolean
 // value. This method returns the newly value of allow_oversize_protos.

+ 44 - 0
ruby/ext/google/protobuf_c/message.c

@@ -178,6 +178,45 @@ VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
   }
 }
 
+VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
+  MessageHeader* self;
+  VALUE method_name, method_str;
+  char* name;
+  size_t name_len;
+  bool setter;
+  const upb_oneofdef* o;
+  const upb_fielddef* f;
+
+  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+  if (argc < 1) {
+    rb_raise(rb_eArgError, "Expected method name as first argument.");
+  }
+  method_name = argv[0];
+  if (!SYMBOL_P(method_name)) {
+    rb_raise(rb_eArgError, "Expected symbol as method name.");
+  }
+  method_str = rb_id2str(SYM2ID(method_name));
+  name = RSTRING_PTR(method_str);
+  name_len = RSTRING_LEN(method_str);
+  setter = false;
+
+  // Setters have names that end in '='.
+  if (name[name_len - 1] == '=') {
+    setter = true;
+    name_len--;
+  }
+
+  // See if this name corresponds to either a oneof or field in this message.
+  if (!upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len, &f,
+                             &o)) {
+    return rb_call_super(argc, argv);
+  }
+  if (o != NULL) {
+    return setter ? Qfalse : Qtrue;
+  }
+  return Qtrue;
+}
+
 int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
   MessageHeader* self;
   VALUE method_str;
@@ -305,6 +344,9 @@ VALUE Message_deep_copy(VALUE _self) {
 VALUE Message_eq(VALUE _self, VALUE _other) {
   MessageHeader* self;
   MessageHeader* other;
+  if (TYPE(_self) != TYPE(_other)) {
+    return Qfalse;
+  }
   TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
   TypedData_Get_Struct(_other, MessageHeader, &Message_type, other);
 
@@ -459,6 +501,8 @@ VALUE build_class_from_descriptor(Descriptor* desc) {
 
   rb_define_method(klass, "method_missing",
                    Message_method_missing, -1);
+  rb_define_method(klass, "respond_to_missing?",
+                   Message_respond_to_missing, -1);
   rb_define_method(klass, "initialize", Message_initialize, -1);
   rb_define_method(klass, "dup", Message_dup, 0);
   // Also define #clone so that we don't inherit Object#clone.

+ 10 - 0
ruby/tests/basic.rb

@@ -1181,5 +1181,15 @@ module BasicTest
       m2 = MapMessage.decode_json(MapMessage.encode_json(m))
       assert m == m2
     end
+
+    def test_comparison_with_arbitrary_object
+      assert_false MapMessage.new == nil
+    end
+
+    def test_respond_to
+      msg = MapMessage.new
+      assert msg.respond_to?(:map_string_int32)
+      assert_false msg.respond_to?(:bacon)
+    end
   end
 end

+ 2 - 0
ruby/travis-test.sh

@@ -10,12 +10,14 @@ test_version() {
     bash --login -c \
       "rvm install $version && rvm use $version && rvm get head && \
        which ruby && \
+       git clean -f && \
        gem install bundler && bundle && \
        rake test"
   else
     bash --login -c \
       "rvm install $version && rvm use $version && \
        which ruby && \
+       git clean -f && \
        gem install bundler && bundle && \
        rake test &&
        cd ../conformance && make test_ruby"

+ 112 - 112
src/Makefile.am

@@ -61,118 +61,118 @@ CLEANFILES = $(protoc_outputs) unittest_proto_middleman \
 MAINTAINERCLEANFILES =   \
   Makefile.in
 
-nobase_include_HEADERS =                                        \
-  google/protobuf/stubs/atomic_sequence_num.h                   \
-  google/protobuf/stubs/atomicops.h                             \
-  google/protobuf/stubs/atomicops_internals_power.h             \
-  google/protobuf/stubs/atomicops_internals_ppc_gcc.h           \
-  google/protobuf/stubs/atomicops_internals_arm64_gcc.h         \
-  google/protobuf/stubs/atomicops_internals_arm_gcc.h           \
-  google/protobuf/stubs/atomicops_internals_arm_qnx.h           \
-  google/protobuf/stubs/atomicops_internals_atomicword_compat.h \
-  google/protobuf/stubs/atomicops_internals_generic_gcc.h       \
-  google/protobuf/stubs/atomicops_internals_macosx.h            \
-  google/protobuf/stubs/atomicops_internals_mips_gcc.h          \
-  google/protobuf/stubs/atomicops_internals_pnacl.h             \
-  google/protobuf/stubs/atomicops_internals_solaris.h           \
-  google/protobuf/stubs/atomicops_internals_tsan.h              \
-  google/protobuf/stubs/atomicops_internals_x86_gcc.h           \
-  google/protobuf/stubs/atomicops_internals_x86_msvc.h          \
-  google/protobuf/stubs/callback.h                              \
-  google/protobuf/stubs/bytestream.h                            \
-  google/protobuf/stubs/casts.h                                 \
-  google/protobuf/stubs/common.h                                \
-  google/protobuf/stubs/fastmem.h                               \
-  google/protobuf/stubs/hash.h                                  \
-  google/protobuf/stubs/logging.h                               \
-  google/protobuf/stubs/macros.h                                \
-  google/protobuf/stubs/mutex.h                                 \
-  google/protobuf/stubs/once.h                                  \
-  google/protobuf/stubs/platform_macros.h                       \
-  google/protobuf/stubs/port.h                                  \
-  google/protobuf/stubs/scoped_ptr.h                            \
-  google/protobuf/stubs/shared_ptr.h                            \
-  google/protobuf/stubs/singleton.h                             \
-  google/protobuf/stubs/status.h                                \
-  google/protobuf/stubs/stl_util.h                              \
-  google/protobuf/stubs/stringpiece.h                           \
-  google/protobuf/stubs/template_util.h                         \
-  google/protobuf/stubs/type_traits.h                           \
-  google/protobuf/any.pb.h                                      \
-  google/protobuf/api.pb.h                                      \
-  google/protobuf/any.h                                         \
-  google/protobuf/arena.h                                       \
-  google/protobuf/arenastring.h                                 \
-  google/protobuf/descriptor_database.h                         \
-  google/protobuf/descriptor.h                                  \
-  google/protobuf/descriptor.pb.h                               \
-  google/protobuf/duration.pb.h                                 \
-  google/protobuf/dynamic_message.h                             \
-  google/protobuf/empty.pb.h                                    \
-  google/protobuf/extension_set.h                               \
-  google/protobuf/field_mask.pb.h                               \
-  google/protobuf/generated_enum_reflection.h                   \
-  google/protobuf/generated_enum_util.h                         \
-  google/protobuf/generated_message_reflection.h                \
-  google/protobuf/generated_message_util.h                      \
-  google/protobuf/has_bits.h                                    \
-  google/protobuf/map_entry.h                                   \
-  google/protobuf/map_entry_lite.h                              \
-  google/protobuf/map_field.h                                   \
-  google/protobuf/map_field_inl.h                               \
-  google/protobuf/map_field_lite.h                              \
-  google/protobuf/map.h                                         \
-  google/protobuf/map_type_handler.h                            \
-  google/protobuf/message.h                                     \
-  google/protobuf/message_lite.h                                \
-  google/protobuf/metadata.h                                    \
-  google/protobuf/reflection.h                                  \
-  google/protobuf/reflection_ops.h                              \
-  google/protobuf/repeated_field.h                              \
-  google/protobuf/service.h                                     \
-  google/protobuf/source_context.pb.h                           \
-  google/protobuf/struct.pb.h                                   \
-  google/protobuf/text_format.h                                 \
-  google/protobuf/timestamp.pb.h                                \
-  google/protobuf/type.pb.h                                     \
-  google/protobuf/unknown_field_set.h                           \
-  google/protobuf/wire_format.h                                 \
-  google/protobuf/wire_format_lite.h                            \
-  google/protobuf/wire_format_lite_inl.h                        \
-  google/protobuf/wrappers.pb.h                                 \
-  google/protobuf/io/coded_stream.h                             \
-  $(GZHEADERS)                                                  \
-  google/protobuf/io/printer.h                                  \
-  google/protobuf/io/strtod.h                                   \
-  google/protobuf/io/tokenizer.h                                \
-  google/protobuf/io/zero_copy_stream.h                         \
-  google/protobuf/io/zero_copy_stream_impl.h                    \
-  google/protobuf/io/zero_copy_stream_impl_lite.h               \
-  google/protobuf/compiler/code_generator.h                     \
-  google/protobuf/compiler/command_line_interface.h             \
-  google/protobuf/compiler/importer.h                           \
-  google/protobuf/compiler/parser.h                             \
-  google/protobuf/compiler/plugin.h                             \
-  google/protobuf/compiler/plugin.pb.h                          \
-  google/protobuf/compiler/cpp/cpp_generator.h                  \
-  google/protobuf/compiler/csharp/csharp_generator.h            \
-  google/protobuf/compiler/csharp/csharp_names.h                \
-  google/protobuf/compiler/java/java_generator.h                \
-  google/protobuf/compiler/java/java_names.h                    \
-  google/protobuf/compiler/javanano/javanano_generator.h        \
-  google/protobuf/compiler/js/js_generator.h                    \
-  google/protobuf/compiler/js/well_known_types_embed.h          \
-  google/protobuf/compiler/objectivec/objectivec_generator.h    \
-  google/protobuf/compiler/objectivec/objectivec_helpers.h      \
-  google/protobuf/compiler/php/php_generator.h                  \
-  google/protobuf/compiler/python/python_generator.h            \
-  google/protobuf/compiler/ruby/ruby_generator.h                \
-  google/protobuf/util/type_resolver.h                          \
-  google/protobuf/util/field_comparator.h                       \
-  google/protobuf/util/field_mask_util.h                        \
-  google/protobuf/util/json_util.h                              \
-  google/protobuf/util/time_util.h                              \
-  google/protobuf/util/type_resolver_util.h                     \
+nobase_include_HEADERS =                                         \
+  google/protobuf/stubs/atomic_sequence_num.h                    \
+  google/protobuf/stubs/atomicops.h                              \
+  google/protobuf/stubs/atomicops_internals_power.h              \
+  google/protobuf/stubs/atomicops_internals_ppc_gcc.h            \
+  google/protobuf/stubs/atomicops_internals_arm64_gcc.h          \
+  google/protobuf/stubs/atomicops_internals_arm_gcc.h            \
+  google/protobuf/stubs/atomicops_internals_arm_qnx.h            \
+  google/protobuf/stubs/atomicops_internals_atomicword_compat.h  \
+  google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h \
+  google/protobuf/stubs/atomicops_internals_generic_gcc.h        \
+  google/protobuf/stubs/atomicops_internals_macosx.h             \
+  google/protobuf/stubs/atomicops_internals_mips_gcc.h           \
+  google/protobuf/stubs/atomicops_internals_solaris.h            \
+  google/protobuf/stubs/atomicops_internals_tsan.h               \
+  google/protobuf/stubs/atomicops_internals_x86_gcc.h            \
+  google/protobuf/stubs/atomicops_internals_x86_msvc.h           \
+  google/protobuf/stubs/callback.h                               \
+  google/protobuf/stubs/bytestream.h                             \
+  google/protobuf/stubs/casts.h                                  \
+  google/protobuf/stubs/common.h                                 \
+  google/protobuf/stubs/fastmem.h                                \
+  google/protobuf/stubs/hash.h                                   \
+  google/protobuf/stubs/logging.h                                \
+  google/protobuf/stubs/macros.h                                 \
+  google/protobuf/stubs/mutex.h                                  \
+  google/protobuf/stubs/once.h                                   \
+  google/protobuf/stubs/platform_macros.h                        \
+  google/protobuf/stubs/port.h                                   \
+  google/protobuf/stubs/scoped_ptr.h                             \
+  google/protobuf/stubs/shared_ptr.h                             \
+  google/protobuf/stubs/singleton.h                              \
+  google/protobuf/stubs/status.h                                 \
+  google/protobuf/stubs/stl_util.h                               \
+  google/protobuf/stubs/stringpiece.h                            \
+  google/protobuf/stubs/template_util.h                          \
+  google/protobuf/stubs/type_traits.h                            \
+  google/protobuf/any.pb.h                                       \
+  google/protobuf/api.pb.h                                       \
+  google/protobuf/any.h                                          \
+  google/protobuf/arena.h                                        \
+  google/protobuf/arenastring.h                                  \
+  google/protobuf/descriptor_database.h                          \
+  google/protobuf/descriptor.h                                   \
+  google/protobuf/descriptor.pb.h                                \
+  google/protobuf/duration.pb.h                                  \
+  google/protobuf/dynamic_message.h                              \
+  google/protobuf/empty.pb.h                                     \
+  google/protobuf/extension_set.h                                \
+  google/protobuf/field_mask.pb.h                                \
+  google/protobuf/generated_enum_reflection.h                    \
+  google/protobuf/generated_enum_util.h                          \
+  google/protobuf/generated_message_reflection.h                 \
+  google/protobuf/generated_message_util.h                       \
+  google/protobuf/has_bits.h                                     \
+  google/protobuf/map_entry.h                                    \
+  google/protobuf/map_entry_lite.h                               \
+  google/protobuf/map_field.h                                    \
+  google/protobuf/map_field_inl.h                                \
+  google/protobuf/map_field_lite.h                               \
+  google/protobuf/map.h                                          \
+  google/protobuf/map_type_handler.h                             \
+  google/protobuf/message.h                                      \
+  google/protobuf/message_lite.h                                 \
+  google/protobuf/metadata.h                                     \
+  google/protobuf/reflection.h                                   \
+  google/protobuf/reflection_ops.h                               \
+  google/protobuf/repeated_field.h                               \
+  google/protobuf/service.h                                      \
+  google/protobuf/source_context.pb.h                            \
+  google/protobuf/struct.pb.h                                    \
+  google/protobuf/text_format.h                                  \
+  google/protobuf/timestamp.pb.h                                 \
+  google/protobuf/type.pb.h                                      \
+  google/protobuf/unknown_field_set.h                            \
+  google/protobuf/wire_format.h                                  \
+  google/protobuf/wire_format_lite.h                             \
+  google/protobuf/wire_format_lite_inl.h                         \
+  google/protobuf/wrappers.pb.h                                  \
+  google/protobuf/io/coded_stream.h                              \
+  $(GZHEADERS)                                                   \
+  google/protobuf/io/printer.h                                   \
+  google/protobuf/io/strtod.h                                    \
+  google/protobuf/io/tokenizer.h                                 \
+  google/protobuf/io/zero_copy_stream.h                          \
+  google/protobuf/io/zero_copy_stream_impl.h                     \
+  google/protobuf/io/zero_copy_stream_impl_lite.h                \
+  google/protobuf/compiler/code_generator.h                      \
+  google/protobuf/compiler/command_line_interface.h              \
+  google/protobuf/compiler/importer.h                            \
+  google/protobuf/compiler/parser.h                              \
+  google/protobuf/compiler/plugin.h                              \
+  google/protobuf/compiler/plugin.pb.h                           \
+  google/protobuf/compiler/cpp/cpp_generator.h                   \
+  google/protobuf/compiler/csharp/csharp_generator.h             \
+  google/protobuf/compiler/csharp/csharp_names.h                 \
+  google/protobuf/compiler/java/java_generator.h                 \
+  google/protobuf/compiler/java/java_names.h                     \
+  google/protobuf/compiler/javanano/javanano_generator.h         \
+  google/protobuf/compiler/js/js_generator.h                     \
+  google/protobuf/compiler/js/well_known_types_embed.h           \
+  google/protobuf/compiler/objectivec/objectivec_generator.h     \
+  google/protobuf/compiler/objectivec/objectivec_helpers.h       \
+  google/protobuf/compiler/php/php_generator.h                   \
+  google/protobuf/compiler/python/python_generator.h             \
+  google/protobuf/compiler/ruby/ruby_generator.h                 \
+  google/protobuf/util/type_resolver.h                           \
+  google/protobuf/util/field_comparator.h                        \
+  google/protobuf/util/field_mask_util.h                         \
+  google/protobuf/util/json_util.h                               \
+  google/protobuf/util/time_util.h                               \
+  google/protobuf/util/type_resolver_util.h                      \
   google/protobuf/util/message_differencer.h
 
 lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la

+ 1 - 0
src/google/protobuf/arena.h

@@ -83,6 +83,7 @@ inline void arena_free(void* object, size_t size) {
 #if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation)
   ::operator delete(object, size);
 #else
+  (void)size;
   ::operator delete(object);
 #endif
 }

+ 38 - 9
src/google/protobuf/compiler/command_line_interface.cc

@@ -263,6 +263,12 @@ void AddDefaultProtoPaths(vector<pair<string, string> >* paths) {
     return;
   }
 }
+
+string PluginName(const string& plugin_prefix, const string& directive) {
+  // Assuming the directive starts with "--" and ends with "_out" or "_opt",
+  // strip the "--" and "_out/_opt" and add the plugin prefix.
+  return plugin_prefix + "gen-" + directive.substr(2, directive.size() - 6);
+}
 }  // namespace
 
 // A MultiFileErrorCollector that prints errors to stderr.
@@ -1008,6 +1014,18 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
       return status;
   }
 
+  // Make sure each plugin option has a matching plugin output.
+  for (map<string, string>::const_iterator i = plugin_parameters_.begin();
+       i != plugin_parameters_.end(); ++i) {
+    if (plugins_.find(i->first) == plugins_.end()) {
+      std::cerr << "Unknown flag: "
+                // strip prefix + "gen-" and add back "_opt"
+                << "--" + i->first.substr(plugin_prefix_.size() + 4) + "_opt"
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+  }
+
   // If no --proto_path was given, use the current working directory.
   if (proto_path_.empty()) {
     // Don't use make_pair as the old/default standard library on Solaris
@@ -1338,15 +1356,22 @@ CommandLineInterface::InterpretArgument(const string& name,
         (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) {
       // Check if it's a generator option flag.
       generator_info = FindOrNull(generators_by_option_name_, name);
-      if (generator_info == NULL) {
-        std::cerr << "Unknown flag: " << name << std::endl;
-        return PARSE_ARGUMENT_FAIL;
-      } else {
+      if (generator_info != NULL) {
         string* parameters = &generator_parameters_[generator_info->flag_name];
         if (!parameters->empty()) {
           parameters->append(",");
         }
         parameters->append(value);
+      } else if (HasPrefixString(name, "--") && HasSuffixString(name, "_opt")) {
+        string* parameters =
+            &plugin_parameters_[PluginName(plugin_prefix_, name)];
+        if (!parameters->empty()) {
+          parameters->append(",");
+        }
+        parameters->append(value);
+      } else {
+        std::cerr << "Unknown flag: " << name << std::endl;
+        return PARSE_ARGUMENT_FAIL;
       }
     } else {
       // It's an output flag.  Add it to the output directives.
@@ -1465,12 +1490,16 @@ bool CommandLineInterface::GenerateOutput(
           HasSuffixString(output_directive.name, "_out"))
         << "Bad name for plugin generator: " << output_directive.name;
 
-    // Strip the "--" and "_out" and add the plugin prefix.
-    string plugin_name = plugin_prefix_ + "gen-" +
-        output_directive.name.substr(2, output_directive.name.size() - 6);
-
+    string plugin_name = PluginName(plugin_prefix_ , output_directive.name);
+    string parameters = output_directive.parameter;
+    if (!plugin_parameters_[plugin_name].empty()) {
+      if (!parameters.empty()) {
+        parameters.append(",");
+      }
+      parameters.append(plugin_parameters_[plugin_name]);
+    }
     if (!GeneratePluginOutput(parsed_files, plugin_name,
-                              output_directive.parameter,
+                              parameters,
                               generator_context, &error)) {
       std::cerr << output_directive.name << ": " << error << std::endl;
       return false;

+ 17 - 8
src/google/protobuf/compiler/command_line_interface.h

@@ -144,14 +144,14 @@ class LIBPROTOC_EXPORT CommandLineInterface {
   //   plugin [--out=OUTDIR] [--parameter=PARAMETER] PROTO_FILES < DESCRIPTORS
   // --out indicates the output directory (as passed to the --foo_out
   // parameter); if omitted, the current directory should be used.  --parameter
-  // gives the generator parameter, if any was provided.  The PROTO_FILES list
-  // the .proto files which were given on the compiler command-line; these are
-  // the files for which the plugin is expected to generate output code.
-  // Finally, DESCRIPTORS is an encoded FileDescriptorSet (as defined in
-  // descriptor.proto).  This is piped to the plugin's stdin.  The set will
-  // include descriptors for all the files listed in PROTO_FILES as well as
-  // all files that they import.  The plugin MUST NOT attempt to read the
-  // PROTO_FILES directly -- it must use the FileDescriptorSet.
+  // gives the generator parameter, if any was provided (see below).  The
+  // PROTO_FILES list the .proto files which were given on the compiler
+  // command-line; these are the files for which the plugin is expected to
+  // generate output code.  Finally, DESCRIPTORS is an encoded FileDescriptorSet
+  // (as defined in descriptor.proto).  This is piped to the plugin's stdin.
+  // The set will include descriptors for all the files listed in PROTO_FILES as
+  // well as all files that they import.  The plugin MUST NOT attempt to read
+  // the PROTO_FILES directly -- it must use the FileDescriptorSet.
   //
   // The plugin should generate whatever files are necessary, as code generators
   // normally do.  It should write the names of all files it generates to
@@ -159,6 +159,13 @@ class LIBPROTOC_EXPORT CommandLineInterface {
   // names or relative to the current directory.  If any errors occur, error
   // messages should be written to stderr.  If an error is fatal, the plugin
   // should exit with a non-zero exit code.
+  //
+  // Plugins can have generator parameters similar to normal built-in
+  // generators. Extra generator parameters can be passed in via a matching
+  // "_opt" parameter. For example:
+  //   protoc --plug_out=enable_bar:outdir --plug_opt=enable_baz
+  // This will pass "enable_bar,enable_baz" as the parameter to the plugin.
+  //
   void AllowPlugins(const string& exe_name_prefix);
 
   // Run the Protocol Compiler with the given command-line parameters.
@@ -314,6 +321,8 @@ class LIBPROTOC_EXPORT CommandLineInterface {
   //   protoc --foo_out=outputdir --foo_opt=enable_bar ...
   // Then there will be an entry ("--foo_out", "enable_bar") in this map.
   std::map<string, string> generator_parameters_;
+  // Similar to generator_parameters_, but stores the parameters for plugins.
+  std::map<string, string> plugin_parameters_;
 
   // See AllowPlugins().  If this is empty, plugins aren't allowed.
   string plugin_prefix_;

+ 38 - 0
src/google/protobuf/compiler/command_line_interface_unittest.cc

@@ -653,6 +653,44 @@ TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) {
       "test_generator", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b");
 }
 
+TEST_F(CommandLineInterfaceTest, ExtraPluginParameters) {
+  // Test that generator parameters specified with the option flag are
+  // correctly passed to the code generator.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+  // Create the "a" and "b" sub-directories.
+  CreateTempDir("a");
+  CreateTempDir("b");
+
+  Run("protocol_compiler "
+      "--plug_opt=foo1 "
+      "--plug_out=bar:$tmpdir/a "
+      "--plug_opt=foo2 "
+      "--plug_out=baz:$tmpdir/b "
+      "--plug_opt=foo3 "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated(
+      "test_plugin", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a");
+  ExpectGenerated(
+      "test_plugin", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b");
+}
+
+TEST_F(CommandLineInterfaceTest, UnrecognizedExtraParameters) {
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "message Foo {}\n");
+
+  Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+      "--unknown_plug_opt=Foo "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectErrorSubstring("Unknown flag: --unknown_plug_opt");
+}
+
 TEST_F(CommandLineInterfaceTest, Insert) {
   // Test running a generator that inserts code into another's output.
 

+ 4 - 4
src/google/protobuf/compiler/mock_code_generator.cc

@@ -61,7 +61,7 @@ namespace compiler {
 // comma-separated string.
 string CommaSeparatedList(const std::vector<const FileDescriptor*> all_files) {
   std::vector<string> names;
-  for (int i = 0; i < all_files.size(); i++) {
+  for (size_t i = 0; i < all_files.size(); i++) {
     names.push_back(all_files[i]->name());
   }
   return Join(names, ",");
@@ -98,7 +98,7 @@ void MockCodeGenerator::ExpectGenerated(
   while (!lines.empty() && lines.back().empty()) {
     lines.pop_back();
   }
-  for (int i = 0; i < lines.size(); i++) {
+  for (size_t i = 0; i < lines.size(); i++) {
     lines[i] += "\n";
   }
 
@@ -115,7 +115,7 @@ void MockCodeGenerator::ExpectGenerated(
   EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]);
   EXPECT_EQ(kSecondInsertionPoint, lines[2 + insertion_list.size() * 2]);
 
-  for (int i = 0; i < insertion_list.size(); i++) {
+  for (size_t i = 0; i < insertion_list.size(); i++) {
     EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert",
                                    file, file, first_message_name),
               lines[1 + i]);
@@ -171,7 +171,7 @@ bool MockCodeGenerator::Generate(
     SplitStringUsing(StripPrefixString(parameter, "insert="),
                      ",", &insert_into);
 
-    for (int i = 0; i < insert_into.size(); i++) {
+    for (size_t i = 0; i < insert_into.size(); i++) {
       {
         google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->OpenForInsert(
             GetOutputFileName(insert_into[i], file), kFirstInsertionPointName));

+ 16 - 2
src/google/protobuf/compiler/php/php_generator.cc

@@ -70,6 +70,16 @@ void GenerateEnum(const google::protobuf::EnumDescriptor* en,
 void Indent(google::protobuf::io::Printer* printer);
 void Outdent(google::protobuf::io::Printer* printer);
 
+std::string MessagePrefix(const google::protobuf::Descriptor* message) {
+  // Empty cannot be php class name.
+  if (message->name() == "Empty" &&
+      message->file()->package() == "google.protobuf") {
+    return "GPB";
+  } else {
+    return "";
+  }
+}
+
 std::string MessageName(const google::protobuf::Descriptor* message,
                         bool is_descriptor) {
   string message_name = message->name();
@@ -78,6 +88,8 @@ std::string MessageName(const google::protobuf::Descriptor* message,
     message_name = descriptor->name() + '_' + message_name;
     descriptor = descriptor->containing_type();
   }
+  message_name = MessagePrefix(message) + message_name;
+
   return PhpName(message->file()->package(), is_descriptor) + '\\' +
          message_name;
 }
@@ -483,8 +495,10 @@ void GenerateMessage(const string& name_prefix,
     return;
   }
 
-  string message_name = name_prefix.empty()?
-      message->name() : name_prefix + "_" + message->name();
+  string message_name =
+      name_prefix.empty()
+          ? message->name()
+          : name_prefix + "_" + MessagePrefix(message) + message->name();
 
   printer->Print(
       "class @name@ extends \\Google\\Protobuf\\Internal\\Message\n"

+ 1 - 2
src/google/protobuf/repeated_field.h

@@ -686,8 +686,7 @@ inline const Message& GenericTypeHandler<Message>::default_instance() {
   return *null;
 }
 
-
-class StringTypeHandler {
+class LIBPROTOBUF_EXPORT StringTypeHandler {
  public:
   typedef string Type;
 

+ 9 - 1
src/google/protobuf/stubs/atomicops.h

@@ -196,14 +196,22 @@ Atomic64 Release_Load(volatile const Atomic64* ptr);
 
 // Apple.
 #elif defined(GOOGLE_PROTOBUF_OS_APPLE)
+#if __has_feature(cxx_atomic) || _GNUC_VER >= 407
+#include <google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h>
+#else  // __has_feature(cxx_atomic) || _GNUC_VER >= 407
 #include <google/protobuf/stubs/atomicops_internals_macosx.h>
+#endif  // __has_feature(cxx_atomic) || _GNUC_VER >= 407
 
 // GCC.
 #elif defined(__GNUC__)
 #if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64)
 #include <google/protobuf/stubs/atomicops_internals_x86_gcc.h>
 #elif defined(GOOGLE_PROTOBUF_ARCH_ARM) && defined(__linux__)
+#if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4))
+#include <google/protobuf/stubs/atomicops_internals_generic_gcc.h>
+#else
 #include <google/protobuf/stubs/atomicops_internals_arm_gcc.h>
+#endif
 #elif defined(GOOGLE_PROTOBUF_ARCH_AARCH64)
 #include <google/protobuf/stubs/atomicops_internals_arm64_gcc.h>
 #elif defined(GOOGLE_PROTOBUF_ARCH_ARM_QNX)
@@ -213,7 +221,7 @@ Atomic64 Release_Load(volatile const Atomic64* ptr);
 #elif defined(GOOGLE_PROTOBUF_ARCH_POWER)
 #include <google/protobuf/stubs/atomicops_internals_power.h>
 #elif defined(__native_client__)
-#include <google/protobuf/stubs/atomicops_internals_pnacl.h>
+#include <google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h>
 #elif defined(GOOGLE_PROTOBUF_ARCH_PPC)
 #include <google/protobuf/stubs/atomicops_internals_ppc_gcc.h>
 #elif (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4))

+ 3 - 3
src/google/protobuf/stubs/atomicops_internals_pnacl.h → src/google/protobuf/stubs/atomicops_internals_generic_c11_atomic.h

@@ -30,8 +30,8 @@
 
 // This file is an internal atomic implementation, use atomicops.h instead.
 
-#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
-#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_C11_ATOMIC_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_C11_ATOMIC_H_
 
 #include <atomic>
 
@@ -228,4 +228,4 @@ inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
 }  // namespace protobuf
 }  // namespace google
 
-#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_C11_ATOMIC_H_

+ 5 - 5
src/google/protobuf/stubs/atomicops_internals_generic_gcc.h

@@ -38,7 +38,7 @@ namespace internal {
 inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
                                          Atomic32 old_value,
                                          Atomic32 new_value) {
-  __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
+  __atomic_compare_exchange_n(ptr, &old_value, new_value, false,
                               __ATOMIC_RELAXED, __ATOMIC_RELAXED);
   return old_value;
 }
@@ -61,7 +61,7 @@ inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
 inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
                                        Atomic32 old_value,
                                        Atomic32 new_value) {
-  __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
+  __atomic_compare_exchange_n(ptr, &old_value, new_value, false,
                               __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
   return old_value;
 }
@@ -69,7 +69,7 @@ inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
 inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
                                        Atomic32 old_value,
                                        Atomic32 new_value) {
-  __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
+  __atomic_compare_exchange_n(ptr, &old_value, new_value, false,
                               __ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
   return old_value;
 }
@@ -115,7 +115,7 @@ inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
 inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
                                        Atomic64 old_value,
                                        Atomic64 new_value) {
-  __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
+  __atomic_compare_exchange_n(ptr, &old_value, new_value, false,
                               __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
   return old_value;
 }
@@ -123,7 +123,7 @@ inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
 inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
                                          Atomic64 old_value,
                                          Atomic64 new_value) {
-  __atomic_compare_exchange_n(ptr, &old_value, new_value, true,
+  __atomic_compare_exchange_n(ptr, &old_value, new_value, false,
                               __ATOMIC_RELAXED, __ATOMIC_RELAXED);
   return old_value;
 }

+ 2 - 2
src/google/protobuf/stubs/platform_macros.h

@@ -114,11 +114,11 @@ GOOGLE_PROTOBUF_PLATFORM_ERROR
 
 #undef GOOGLE_PROTOBUF_PLATFORM_ERROR
 
-#if defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
+#if defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE) || defined(__OpenBSD__)
 // Android ndk does not support the __thread keyword very well yet. Here
 // we use pthread_key_create()/pthread_getspecific()/... methods for
 // TLS support on android.
-// iOS also does not support the __thread keyword.
+// iOS and OpenBSD also do not support the __thread keyword.
 #define GOOGLE_PROTOBUF_NO_THREADLOCAL
 #endif
 

+ 1 - 9
src/google/protobuf/stubs/type_traits.h

@@ -139,18 +139,10 @@ template<> struct is_integral<int> : true_type { };
 template<> struct is_integral<unsigned int> : true_type { };
 template<> struct is_integral<long> : true_type { };
 template<> struct is_integral<unsigned long> : true_type { };
-#ifdef HAVE_LONG_LONG
+#if defined(HAVE_LONG_LONG) || defined(_MSC_VER)
 template<> struct is_integral<long long> : true_type { };
 template<> struct is_integral<unsigned long long> : true_type { };
 #endif
-#if defined(_MSC_VER)
-// With VC, __int8, __int16, and __int32 are synonymous with standard types
-// with the same size, but __int64 has not equivalent (i.e., it's neither
-// long, nor long long and should be treated differnetly).
-// https://msdn.microsoft.com/en-us/library/29dh1w7z.aspx
-template<> struct is_integral<__int64> : true_type { };
-template<> struct is_integral<unsigned __int64> : true_type {};
-#endif
 template <class T> struct is_integral<const T> : is_integral<T> { };
 template <class T> struct is_integral<volatile T> : is_integral<T> { };
 template <class T> struct is_integral<const volatile T> : is_integral<T> { };

+ 4 - 4
src/google/protobuf/util/internal/constants.h

@@ -50,16 +50,16 @@ const char kRfc3339TimeFormat[] = "%E4Y-%m-%dT%H:%M:%S";
 const char kRfc3339TimeFormatNoPadding[] = "%Y-%m-%dT%H:%M:%S";
 
 // Minimun seconds allowed in a google.protobuf.Timestamp value.
-const int64 kTimestampMinSeconds = -62135596800;
+const int64 kTimestampMinSeconds = -62135596800LL;
 
 // Maximum seconds allowed in a google.protobuf.Timestamp value.
-const int64 kTimestampMaxSeconds = 253402300799;
+const int64 kTimestampMaxSeconds = 253402300799LL;
 
 // Minimum seconds allowed in a google.protobuf.Duration value.
-const int64 kDurationMinSeconds = -315576000000;
+const int64 kDurationMinSeconds = -315576000000LL;
 
 // Maximum seconds allowed in a google.protobuf.Duration value.
-const int64 kDurationMaxSeconds = 315576000000;
+const int64 kDurationMaxSeconds = 315576000000LL;
 
 // Nano seconds in a second.
 const int32 kNanosPerSecond = 1000000000;

+ 6 - 2
src/google/protobuf/util/internal/protostream_objectsource.cc

@@ -1028,8 +1028,11 @@ bool ProtoStreamObjectSource::IsMap(
   // TODO(xiaofeng): Unify option names.
   return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE &&
          (GetBoolOptionOrDefault(field_type->options(),
-                                 "google.protobuf.MessageOptions.map_entry", false) ||
-          GetBoolOptionOrDefault(field_type->options(), "map_entry", false));
+                                 "google.protobuf.MessageOptions.map_entry",
+                                 false) ||
+          GetBoolOptionOrDefault(field_type->options(), "map_entry", false) ||
+          GetBoolOptionOrDefault(field_type->options(),
+                                 "proto2.MessageOptions.map_entry", false));
 }
 
 std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos(
@@ -1125,3 +1128,4 @@ const string FormatNanos(uint32 nanos, bool with_trailing_zeros) {
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
+

+ 6 - 2
src/google/protobuf/util/internal/protostream_objectwriter.cc

@@ -1240,8 +1240,11 @@ bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) {
 
   // TODO(xiaofeng): Unify option names.
   return GetBoolOptionOrDefault(field_type->options(),
-                                "google.protobuf.MessageOptions.map_entry", false) ||
-         GetBoolOptionOrDefault(field_type->options(), "map_entry", false);
+                                "google.protobuf.MessageOptions.map_entry",
+                                false) ||
+         GetBoolOptionOrDefault(field_type->options(), "map_entry", false) ||
+         GetBoolOptionOrDefault(field_type->options(),
+                                "proto2.MessageOptions.map_entry", false);
 }
 
 bool ProtoStreamObjectWriter::IsAny(const google::protobuf::Field& field) {
@@ -1266,3 +1269,4 @@ bool ProtoStreamObjectWriter::IsStructListValue(
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
+

+ 15 - 6
src/google/protobuf/util/internal/utility.cc

@@ -356,15 +356,23 @@ bool IsValidBoolString(const string& bool_string) {
 
 bool IsMap(const google::protobuf::Field& field,
            const google::protobuf::Type& type) {
-  return (field.cardinality() ==
-              google::protobuf::Field_Cardinality_CARDINALITY_REPEATED &&
-          GetBoolOptionOrDefault(type.options(),
-                                 "google.protobuf.MessageOptions.map_entry", false));
+  return (
+      field.cardinality() ==
+          google::protobuf::Field_Cardinality_CARDINALITY_REPEATED &&
+      (GetBoolOptionOrDefault(
+           type.options(), "google.protobuf.MessageOptions.map_entry", false) ||
+       GetBoolOptionOrDefault(type.options(), "proto2.MessageOptions.map_entry",
+                              false)));
 }
 
 bool IsMessageSetWireFormat(const google::protobuf::Type& type) {
-  return GetBoolOptionOrDefault(
-      type.options(), "google.protobuf.MessageOptions.message_set_wire_format", false);
+  return (
+      GetBoolOptionOrDefault(
+          type.options(),
+          "google.protobuf.MessageOptions.message_set_wire_format", false) ||
+      GetBoolOptionOrDefault(type.options(),
+                             "proto2.MessageOptions.message_set_wire_format",
+                             false));
 }
 
 string DoubleAsString(double value) {
@@ -404,3 +412,4 @@ bool SafeStrToFloat(StringPiece str, float* value) {
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
+

+ 30 - 1
tests.sh

@@ -358,6 +358,16 @@ use_php_zts() {
   ln -sfn "/usr/local/php-${VERSION}-zts/bin/phpize" $PHPIZE
 }
 
+use_php_bc() {
+  VERSION=$1
+  PHP=`which php`
+  PHP_CONFIG=`which php-config`
+  PHPIZE=`which phpize`
+  ln -sfn "/usr/local/php-${VERSION}-bc/bin/php" $PHP
+  ln -sfn "/usr/local/php-${VERSION}-bc/bin/php-config" $PHP_CONFIG
+  ln -sfn "/usr/local/php-${VERSION}-bc/bin/phpize" $PHPIZE
+}
+
 build_php5.5() {
   use_php 5.5
   rm -rf vendor
@@ -376,6 +386,19 @@ build_php5.5_zts_c() {
   cd php/tests && /bin/bash ./test.sh && cd ../..
 }
 
+build_php5.5_32() {
+  use_php_bc 5.5
+  rm -rf vendor
+  cp -r /usr/local/vendor-5.5 vendor
+  ./vendor/bin/phpunit
+}
+
+build_php5.5_c_32() {
+  use_php_bc 5.5
+  wget https://phar.phpunit.de/phpunit-old.phar -O /usr/bin/phpunit
+  cd php/tests && /bin/bash ./test.sh && cd ../..
+}
+
 build_php5.6() {
   use_php 5.6
   rm -rf vendor
@@ -391,7 +414,8 @@ build_php5.6_c() {
 build_php5.6_mac() {
   # Install PHP
   curl -s https://php-osx.liip.ch/install.sh | bash -s 5.6
-  export PATH="/usr/local/php5-5.6.25-20160831-101628/bin:$PATH"
+  PHP_FOLDER=`find /usr/local -type d -name "php5-5.6*"`  # The folder name may change upon time
+  export PATH="$PHP_FOLDER/bin:$PATH"
 
   # Install phpunit
   curl https://phar.phpunit.de/phpunit.phar -L -o phpunit.phar
@@ -429,6 +453,11 @@ build_php_all() {
   build_php5.5_zts_c
 }
 
+build_php_all_32() {
+  build_php5.5_32
+  build_php5.5_c_32
+}
+
 # Note: travis currently does not support testing more than one language so the
 # .travis.yml cheats and claims to only be cpp.  If they add multiple language
 # support, this should probably get updated to install steps and/or