aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am3
-rw-r--r--composer.json6
-rw-r--r--configure.ac1
-rw-r--r--conformance/conformance_test.cc31
-rw-r--r--csharp/src/Google.Protobuf.Test/ByteStringTest.cs55
-rw-r--r--csharp/src/Google.Protobuf.Test/project.json1
-rw-r--r--csharp/src/Google.Protobuf/ByteString.cs53
-rw-r--r--csharp/src/global.json5
-rw-r--r--docs/third_party.md1
-rw-r--r--js/message_test.js11
-rw-r--r--js/test8.proto (renamed from src/google/protobuf/arena_nc.cc)25
-rw-r--r--m4/ax_prog_cc_for_build.m4125
-rw-r--r--m4/ax_prog_cxx_for_build.m4110
-rwxr-xr-xobjectivec/DevTools/full_mac_build.sh8
-rw-r--r--objectivec/GPBArray.m4
-rw-r--r--objectivec/GPBDictionary.m8
-rw-r--r--objectivec/GPBMessage.m16
-rw-r--r--objectivec/GPBUtilities.m16
-rw-r--r--objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj4
-rw-r--r--objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj4
-rw-r--r--objectivec/Tests/GPBArrayTests.m173
-rw-r--r--objectivec/Tests/GPBDictionaryTests.m186
-rw-r--r--objectivec/Tests/GPBMessageTests.m31
-rw-r--r--php/src/Google/Protobuf/Internal/InputStream.php75
-rw-r--r--php/tests/php_implementation_test.php30
-rwxr-xr-xpython/google/protobuf/internal/decoder.py16
-rw-r--r--src/Makefile.am13
-rw-r--r--src/google/protobuf/arena_nc_test.py61
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc21
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc16
-rw-r--r--src/google/protobuf/compiler/js/embed.cc4
-rwxr-xr-xsrc/google/protobuf/compiler/js/js_generator.cc19
-rw-r--r--src/google/protobuf/stubs/callback.h30
33 files changed, 995 insertions, 167 deletions
diff --git a/Makefile.am b/Makefile.am
index 4ece5217..6aa7e800 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -186,6 +186,7 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs \
csharp/src/Google.Protobuf/WireFormat.cs \
csharp/src/Google.Protobuf/project.json \
+ csharp/src/global.json \
csharp/src/packages/repositories.config
java_EXTRA_DIST= \
@@ -525,6 +526,7 @@ objectivec_EXTRA_DIST= \
objectivec/Tests/GPBDictionaryTests+String.m \
objectivec/Tests/GPBDictionaryTests+UInt32.m \
objectivec/Tests/GPBDictionaryTests+UInt64.m \
+ objectivec/Tests/GPBDictionaryTests.m \
objectivec/Tests/GPBDictionaryTests.pddm \
objectivec/Tests/GPBMessageTests+Merge.m \
objectivec/Tests/GPBMessageTests+Runtime.m \
@@ -852,6 +854,7 @@ js_EXTRA_DIST= \
js/test3.proto \
js/test4.proto \
js/test5.proto \
+ js/test8.proto \
js/test_bootstrap.js \
js/testbinary.proto \
js/testempty.proto
diff --git a/composer.json b/composer.json
index 2833f0a2..2b04e079 100644
--- a/composer.json
+++ b/composer.json
@@ -13,11 +13,11 @@
},
"autoload": {
"psr-4": {
- "Google\\Protobuf\\Internal\\": "src/Google/Protobuf/Internal",
- "GPBMetadata\\Google\\Protobuf\\Internal\\": "src/GPBMetadata/Google/Protobuf/Internal"
+ "Google\\Protobuf\\Internal\\": "php/src/Google/Protobuf/Internal",
+ "GPBMetadata\\Google\\Protobuf\\Internal\\": "php/src/GPBMetadata/Google/Protobuf/Internal"
},
"files": [
- "src/Google/Protobuf/descriptor.php"
+ "php/src/Google/Protobuf/descriptor.php"
]
}
}
diff --git a/configure.ac b/configure.ac
index d1e913c6..10fbdbd2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -60,6 +60,7 @@ AC_ARG_WITH([protoc],
# Checks for programs.
AC_PROG_CC
AC_PROG_CXX
+AC_PROG_CXX_FOR_BUILD
AC_LANG([C++])
ACX_USE_SYSTEM_EXTENSIONS
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc
index dd266d15..1e5387a5 100644
--- a/conformance/conformance_test.cc
+++ b/conformance/conformance_test.cc
@@ -109,13 +109,18 @@ string cat(const string& a, const string& b,
// The maximum number of bytes that it takes to encode a 64-bit varint.
#define VARINT_MAX_LEN 10
-size_t vencode64(uint64_t val, char *buf) {
+size_t vencode64(uint64_t val, int over_encoded_bytes, char *buf) {
if (val == 0) { buf[0] = 0; return 1; }
size_t i = 0;
while (val) {
uint8_t byte = val & 0x7fU;
val >>= 7;
- if (val) byte |= 0x80U;
+ if (val || over_encoded_bytes) byte |= 0x80U;
+ buf[i++] = byte;
+ }
+ while (over_encoded_bytes--) {
+ assert(i < 10);
+ uint8_t byte = over_encoded_bytes ? 0x80 : 0;
buf[i++] = byte;
}
return i;
@@ -123,7 +128,15 @@ size_t vencode64(uint64_t val, char *buf) {
string varint(uint64_t x) {
char buf[VARINT_MAX_LEN];
- size_t len = vencode64(x, buf);
+ size_t len = vencode64(x, 0, buf);
+ return string(buf, len);
+}
+
+// Encodes a varint that is |extra| bytes longer than it needs to be, but still
+// valid.
+string longvarint(uint64_t x, int extra) {
+ char buf[VARINT_MAX_LEN];
+ size_t len = vencode64(x, extra, buf);
return string(buf, len);
}
@@ -744,13 +757,23 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
});
TestValidDataForType(FieldDescriptor::TYPE_INT32, {
{varint(12345), "12345"},
+ {longvarint(12345, 2), "12345"},
+ {longvarint(12345, 7), "12345"},
{varint(kInt32Max), std::to_string(kInt32Max)},
{varint(kInt32Min), std::to_string(kInt32Min)},
+ {varint(1LL << 33), std::to_string(static_cast<int32>(1LL << 33))},
+ {varint((1LL << 33) - 1),
+ std::to_string(static_cast<int32>((1LL << 33) - 1))},
});
TestValidDataForType(FieldDescriptor::TYPE_UINT32, {
{varint(12345), "12345"},
+ {longvarint(12345, 2), "12345"},
+ {longvarint(12345, 7), "12345"},
{varint(kUint32Max), std::to_string(kUint32Max)}, // UINT32_MAX
- {varint(0), "0"}
+ {varint(0), "0"},
+ {varint(1LL << 33), std::to_string(static_cast<uint32>(1LL << 33))},
+ {varint((1LL << 33) - 1),
+ std::to_string(static_cast<uint32>((1LL << 33) - 1))},
});
TestValidDataForType(FieldDescriptor::TYPE_FIXED64, {
{u64(12345), "12345"},
diff --git a/csharp/src/Google.Protobuf.Test/ByteStringTest.cs b/csharp/src/Google.Protobuf.Test/ByteStringTest.cs
index ff2444a3..21aeb310 100644
--- a/csharp/src/Google.Protobuf.Test/ByteStringTest.cs
+++ b/csharp/src/Google.Protobuf.Test/ByteStringTest.cs
@@ -33,6 +33,10 @@
using System;
using System.Text;
using NUnit.Framework;
+using System.IO;
+#if !DOTNET35
+using System.Threading.Tasks;
+#endif
namespace Google.Protobuf
{
@@ -169,6 +173,56 @@ namespace Google.Protobuf
}
[Test]
+ public void FromStream_Seekable()
+ {
+ var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
+ // Consume the first byte, just to test that it's "from current position"
+ stream.ReadByte();
+ var actual = ByteString.FromStream(stream);
+ ByteString expected = ByteString.CopyFrom(2, 3, 4, 5);
+ Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
+ }
+
+ [Test]
+ public void FromStream_NotSeekable()
+ {
+ var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
+ // Consume the first byte, just to test that it's "from current position"
+ stream.ReadByte();
+ // Wrap the original stream in LimitedInputStream, which has CanSeek=false
+ var limitedStream = new LimitedInputStream(stream, 3);
+ var actual = ByteString.FromStream(limitedStream);
+ ByteString expected = ByteString.CopyFrom(2, 3, 4);
+ Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
+ }
+
+#if !DOTNET35
+ [Test]
+ public async Task FromStreamAsync_Seekable()
+ {
+ var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
+ // Consume the first byte, just to test that it's "from current position"
+ stream.ReadByte();
+ var actual = await ByteString.FromStreamAsync(stream);
+ ByteString expected = ByteString.CopyFrom(2, 3, 4, 5);
+ Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
+ }
+
+ [Test]
+ public async Task FromStreamAsync_NotSeekable()
+ {
+ var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
+ // Consume the first byte, just to test that it's "from current position"
+ stream.ReadByte();
+ // Wrap the original stream in LimitedInputStream, which has CanSeek=false
+ var limitedStream = new LimitedInputStream(stream, 3);
+ var actual = await ByteString.FromStreamAsync(limitedStream);
+ ByteString expected = ByteString.CopyFrom(2, 3, 4);
+ Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
+ }
+#endif
+
+ [Test]
public void GetHashCode_Regression()
{
// We used to have an awful hash algorithm where only the last four
@@ -179,6 +233,5 @@ namespace Google.Protobuf
ByteString b2 = ByteString.CopyFrom(200, 1, 2, 3, 4);
Assert.AreNotEqual(b1.GetHashCode(), b2.GetHashCode());
}
-
}
} \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/project.json b/csharp/src/Google.Protobuf.Test/project.json
index 3a73bf7a..9f739f90 100644
--- a/csharp/src/Google.Protobuf.Test/project.json
+++ b/csharp/src/Google.Protobuf.Test/project.json
@@ -27,6 +27,7 @@
"testRunner": "nunit",
"frameworks": {
+ "net451": {},
"netcoreapp1.0": {
"imports" : [ "dnxcore50", "netcoreapp1.0", "portable-net45+win8" ],
"buildOptions": {
diff --git a/csharp/src/Google.Protobuf/ByteString.cs b/csharp/src/Google.Protobuf/ByteString.cs
index 5c652cc3..9973d211 100644
--- a/csharp/src/Google.Protobuf/ByteString.cs
+++ b/csharp/src/Google.Protobuf/ByteString.cs
@@ -35,6 +35,10 @@ using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
+#if !DOTNET35
+using System.Threading;
+using System.Threading.Tasks;
+#endif
namespace Google.Protobuf
{
@@ -142,6 +146,55 @@ namespace Google.Protobuf
}
/// <summary>
+ /// Constructs a <see cref="ByteString"/> from data in the given stream, synchronously.
+ /// </summary>
+ /// <remarks>If successful, <paramref name="stream"/> will be read completely, from the position
+ /// at the start of the call.</remarks>
+ /// <param name="stream">The stream to copy into a ByteString.</param>
+ /// <returns>A ByteString with content read from the given stream.</returns>
+ public static ByteString FromStream(Stream stream)
+ {
+ ProtoPreconditions.CheckNotNull(stream, nameof(stream));
+ int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0;
+ var memoryStream = new MemoryStream(capacity);
+ stream.CopyTo(memoryStream);
+#if NETSTANDARD1_0
+ byte[] bytes = memoryStream.ToArray();
+#else
+ // Avoid an extra copy if we can.
+ byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray();
+#endif
+ return AttachBytes(bytes);
+ }
+
+#if !DOTNET35
+ /// <summary>
+ /// Constructs a <see cref="ByteString"/> from data in the given stream, asynchronously.
+ /// </summary>
+ /// <remarks>If successful, <paramref name="stream"/> will be read completely, from the position
+ /// at the start of the call.</remarks>
+ /// <param name="stream">The stream to copy into a ByteString.</param>
+ /// <param name="cancellationToken">The cancellation token to use when reading from the stream, if any.</param>
+ /// <returns>A ByteString with content read from the given stream.</returns>
+ public async static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ ProtoPreconditions.CheckNotNull(stream, nameof(stream));
+ int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0;
+ var memoryStream = new MemoryStream(capacity);
+ // We have to specify the buffer size here, as there's no overload accepting the cancellation token
+ // alone. But it's documented to use 81920 by default if not specified.
+ await stream.CopyToAsync(memoryStream, 81920, cancellationToken);
+#if NETSTANDARD1_0
+ byte[] bytes = memoryStream.ToArray();
+#else
+ // Avoid an extra copy if we can.
+ byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray();
+#endif
+ return AttachBytes(bytes);
+ }
+#endif
+
+ /// <summary>
/// Constructs a <see cref="ByteString" /> from the given array. The contents
/// are copied, so further modifications to the array will not
/// be reflected in the returned ByteString.
diff --git a/csharp/src/global.json b/csharp/src/global.json
new file mode 100644
index 00000000..9d5558b1
--- /dev/null
+++ b/csharp/src/global.json
@@ -0,0 +1,5 @@
+{
+ "sdk": {
+ "version": "1.0.0-preview2-003131"
+ }
+}
diff --git a/docs/third_party.md b/docs/third_party.md
index 0bbde914..160090ce 100644
--- a/docs/third_party.md
+++ b/docs/third_party.md
@@ -32,6 +32,7 @@ These are projects we know about implementing Protocol Buffers for other program
* Delphi: http://sourceforge.net/projects/protobuf-delphi/
* Delphi: http://fundementals.sourceforge.net/dl.html
* Elixir: https://github.com/jeremyong/exprotoc
+* Elm: https://github.com/tiziano88/elm-protobuf
* Erlang: http://github.com/ngerakines/erlang_protobuffs/tree/master
* Erlang: http://piqi.org/
* Erlang: https://code.google.com/p/protoc-gen-erl/
diff --git a/js/message_test.js b/js/message_test.js
index 082da944..6d7cdd21 100644
--- a/js/message_test.js
+++ b/js/message_test.js
@@ -39,6 +39,9 @@ goog.require('goog.userAgent');
// CommonJS-LoadFromFile: google-protobuf jspb
goog.require('jspb.Message');
+// CommonJS-LoadFromFile: test8_pb proto.jspb.exttest.nested
+goog.require('proto.jspb.exttest.nested.TestOuterMessage');
+
// CommonJS-LoadFromFile: test5_pb proto.jspb.exttest.beta
goog.require('proto.jspb.exttest.beta.floatingStrField');
@@ -588,6 +591,14 @@ describe('Message test suite', function() {
assertNotUndefined(proto.jspb.exttest.beta.floatingStrField);
});
+ it('testNestedExtensions', function() {
+ var extendable = new proto.jspb.exttest.nested.TestNestedExtensionsMessage();
+ var extension = new proto.jspb.exttest.nested.TestOuterMessage.NestedExtensionMessage(['s1']);
+ extendable.setExtension(proto.jspb.exttest.nested.TestOuterMessage.innerExtension, extension);
+ assertObjectEquals(extension,
+ extendable.getExtension(proto.jspb.exttest.nested.TestOuterMessage.innerExtension));
+ });
+
it('testToObject_extendedObject', function() {
var extension1 = new proto.jspb.test.IsExtension(['ext1field']);
var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2'], true]);
diff --git a/src/google/protobuf/arena_nc.cc b/js/test8.proto
index f2f08427..2ae80dab 100644
--- a/src/google/protobuf/arena_nc.cc
+++ b/js/test8.proto
@@ -28,18 +28,23 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Negative compilation test for arena usage.
+syntax = "proto2";
-#include <google/protobuf/arena.h>
-#include <google/protobuf/unittest.pb.h>
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
-#ifdef TEST_ARENA_PRIVATE_CONSTRUCTOR
+package jspb.exttest.nested;
-namespace google {
-void ArenaPrivateConstructor() {
- google::protobuf::Arena arena;
- protobuf_unittest::TestAllTypes message(&arena);
+message TestNestedExtensionsMessage {
+ optional int32 intfield = 1;
+ extensions 100 to max;
}
-#endif
-} // namespace google
+message TestOuterMessage {
+ message NestedExtensionMessage {
+ optional string ext1 = 1;
+ }
+ extend TestNestedExtensionsMessage {
+ optional NestedExtensionMessage inner_extension = 100;
+ }
+}
diff --git a/m4/ax_prog_cc_for_build.m4 b/m4/ax_prog_cc_for_build.m4
new file mode 100644
index 00000000..77fd346a
--- /dev/null
+++ b/m4/ax_prog_cc_for_build.m4
@@ -0,0 +1,125 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PROG_CC_FOR_BUILD
+#
+# DESCRIPTION
+#
+# This macro searches for a C compiler that generates native executables,
+# that is a C compiler that surely is not a cross-compiler. This can be
+# useful if you have to generate source code at compile-time like for
+# example GCC does.
+#
+# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything
+# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD).
+# The value of these variables can be overridden by the user by specifying
+# a compiler with an environment variable (like you do for standard CC).
+#
+# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object
+# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if
+# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are
+# substituted in the Makefile.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Paolo Bonzini <bonzini@gnu.org>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 8
+
+AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD])
+AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_CPP])dnl
+AC_REQUIRE([AC_EXEEXT])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+
+dnl Use the standard macros, but make them use other variable names
+dnl
+pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl
+pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl
+pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl
+pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl
+pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl
+pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl
+pushdef([ac_cv_objext], ac_cv_build_objext)dnl
+pushdef([ac_exeext], ac_build_exeext)dnl
+pushdef([ac_objext], ac_build_objext)dnl
+pushdef([CC], CC_FOR_BUILD)dnl
+pushdef([CPP], CPP_FOR_BUILD)dnl
+pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl
+pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl
+pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl
+pushdef([host], build)dnl
+pushdef([host_alias], build_alias)dnl
+pushdef([host_cpu], build_cpu)dnl
+pushdef([host_vendor], build_vendor)dnl
+pushdef([host_os], build_os)dnl
+pushdef([ac_cv_host], ac_cv_build)dnl
+pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl
+pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl
+pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl
+pushdef([ac_cv_host_os], ac_cv_build_os)dnl
+pushdef([ac_cpp], ac_build_cpp)dnl
+pushdef([ac_compile], ac_build_compile)dnl
+pushdef([ac_link], ac_build_link)dnl
+
+save_cross_compiling=$cross_compiling
+save_ac_tool_prefix=$ac_tool_prefix
+cross_compiling=no
+ac_tool_prefix=
+
+AC_PROG_CC
+AC_PROG_CPP
+AC_EXEEXT
+
+ac_tool_prefix=$save_ac_tool_prefix
+cross_compiling=$save_cross_compiling
+
+dnl Restore the old definitions
+dnl
+popdef([ac_link])dnl
+popdef([ac_compile])dnl
+popdef([ac_cpp])dnl
+popdef([ac_cv_host_os])dnl
+popdef([ac_cv_host_vendor])dnl
+popdef([ac_cv_host_cpu])dnl
+popdef([ac_cv_host_alias])dnl
+popdef([ac_cv_host])dnl
+popdef([host_os])dnl
+popdef([host_vendor])dnl
+popdef([host_cpu])dnl
+popdef([host_alias])dnl
+popdef([host])dnl
+popdef([LDFLAGS])dnl
+popdef([CPPFLAGS])dnl
+popdef([CFLAGS])dnl
+popdef([CPP])dnl
+popdef([CC])dnl
+popdef([ac_objext])dnl
+popdef([ac_exeext])dnl
+popdef([ac_cv_objext])dnl
+popdef([ac_cv_exeext])dnl
+popdef([ac_cv_prog_cc_g])dnl
+popdef([ac_cv_prog_cc_cross])dnl
+popdef([ac_cv_prog_cc_works])dnl
+popdef([ac_cv_prog_gcc])dnl
+popdef([ac_cv_prog_CPP])dnl
+
+dnl Finally, set Makefile variables
+dnl
+BUILD_EXEEXT=$ac_build_exeext
+BUILD_OBJEXT=$ac_build_objext
+AC_SUBST(BUILD_EXEEXT)dnl
+AC_SUBST(BUILD_OBJEXT)dnl
+AC_SUBST([CFLAGS_FOR_BUILD])dnl
+AC_SUBST([CPPFLAGS_FOR_BUILD])dnl
+AC_SUBST([LDFLAGS_FOR_BUILD])dnl
+])
diff --git a/m4/ax_prog_cxx_for_build.m4 b/m4/ax_prog_cxx_for_build.m4
new file mode 100644
index 00000000..8cc0f73c
--- /dev/null
+++ b/m4/ax_prog_cxx_for_build.m4
@@ -0,0 +1,110 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_prog_cxx_for_build.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PROG_CXX_FOR_BUILD
+#
+# DESCRIPTION
+#
+# This macro searches for a C++ compiler that generates native
+# executables, that is a C++ compiler that surely is not a cross-compiler.
+# This can be useful if you have to generate source code at compile-time
+# like for example GCC does.
+#
+# The macro sets the CXX_FOR_BUILD and CXXCPP_FOR_BUILD macros to anything
+# needed to compile or link (CXX_FOR_BUILD) and preprocess
+# (CXXCPP_FOR_BUILD). The value of these variables can be overridden by
+# the user by specifying a compiler with an environment variable (like you
+# do for standard CXX).
+#
+# LICENSE
+#
+# Copyright (c) 2008 Paolo Bonzini <bonzini@gnu.org>
+# Copyright (c) 2012 Avionic Design GmbH
+#
+# Based on the AX_PROG_CC_FOR_BUILD macro by Paolo Bonzini.
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 2
+
+AU_ALIAS([AC_PROG_CXX_FOR_BUILD], [AX_PROG_CXX_FOR_BUILD])
+AC_DEFUN([AX_PROG_CXX_FOR_BUILD], [dnl
+AC_REQUIRE([AX_PROG_CC_FOR_BUILD])dnl
+AC_REQUIRE([AC_PROG_CXX])dnl
+AC_REQUIRE([AC_PROG_CXXCPP])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+
+dnl Use the standard macros, but make them use other variable names
+dnl
+pushdef([ac_cv_prog_CXXCPP], ac_cv_build_prog_CXXCPP)dnl
+pushdef([ac_cv_prog_gxx], ac_cv_build_prog_gxx)dnl
+pushdef([ac_cv_prog_cxx_works], ac_cv_build_prog_cxx_works)dnl
+pushdef([ac_cv_prog_cxx_cross], ac_cv_build_prog_cxx_cross)dnl
+pushdef([ac_cv_prog_cxx_g], ac_cv_build_prog_cxx_g)dnl
+pushdef([CXX], CXX_FOR_BUILD)dnl
+pushdef([CXXCPP], CXXCPP_FOR_BUILD)dnl
+pushdef([CXXFLAGS], CXXFLAGS_FOR_BUILD)dnl
+pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl
+pushdef([CXXCPPFLAGS], CXXCPPFLAGS_FOR_BUILD)dnl
+pushdef([host], build)dnl
+pushdef([host_alias], build_alias)dnl
+pushdef([host_cpu], build_cpu)dnl
+pushdef([host_vendor], build_vendor)dnl
+pushdef([host_os], build_os)dnl
+pushdef([ac_cv_host], ac_cv_build)dnl
+pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl
+pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl
+pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl
+pushdef([ac_cv_host_os], ac_cv_build_os)dnl
+pushdef([ac_cxxcpp], ac_build_cxxcpp)dnl
+pushdef([ac_compile], ac_build_compile)dnl
+pushdef([ac_link], ac_build_link)dnl
+
+save_cross_compiling=$cross_compiling
+save_ac_tool_prefix=$ac_tool_prefix
+cross_compiling=no
+ac_tool_prefix=
+
+AC_PROG_CXX
+AC_PROG_CXXCPP
+
+ac_tool_prefix=$save_ac_tool_prefix
+cross_compiling=$save_cross_compiling
+
+dnl Restore the old definitions
+dnl
+popdef([ac_link])dnl
+popdef([ac_compile])dnl
+popdef([ac_cxxcpp])dnl
+popdef([ac_cv_host_os])dnl
+popdef([ac_cv_host_vendor])dnl
+popdef([ac_cv_host_cpu])dnl
+popdef([ac_cv_host_alias])dnl
+popdef([ac_cv_host])dnl
+popdef([host_os])dnl
+popdef([host_vendor])dnl
+popdef([host_cpu])dnl
+popdef([host_alias])dnl
+popdef([host])dnl
+popdef([CXXCPPFLAGS])dnl
+popdef([CPPFLAGS])dnl
+popdef([CXXFLAGS])dnl
+popdef([CXXCPP])dnl
+popdef([CXX])dnl
+popdef([ac_cv_prog_cxx_g])dnl
+popdef([ac_cv_prog_cxx_cross])dnl
+popdef([ac_cv_prog_cxx_works])dnl
+popdef([ac_cv_prog_gxx])dnl
+popdef([ac_cv_prog_CXXCPP])dnl
+
+dnl Finally, set Makefile variables
+dnl
+AC_SUBST([CXXFLAGS_FOR_BUILD])dnl
+AC_SUBST([CXXCPPFLAGS_FOR_BUILD])dnl
+])
diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh
index ef8fb740..ea9fd273 100755
--- a/objectivec/DevTools/full_mac_build.sh
+++ b/objectivec/DevTools/full_mac_build.sh
@@ -265,6 +265,14 @@ if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then
-destination "platform=iOS Simulator,name=iPad Pro (9.7 inch),OS=10.1" # 64bit
)
;;
+ 8.2* )
+ XCODEBUILD_TEST_BASE_IOS+=(
+ -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit
+ -destination "platform=iOS Simulator,name=iPhone 7,OS=10.2" # 64bit
+ -destination "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit
+ -destination "platform=iOS Simulator,name=iPad Pro (9.7 inch),OS=10.2" # 64bit
+ )
+ ;;
* )
echo "Time to update the simulator targets for Xcode ${XCODE_VERSION}"
exit 2
diff --git a/objectivec/GPBArray.m b/objectivec/GPBArray.m
index ae57747d..f401631d 100644
--- a/objectivec/GPBArray.m
+++ b/objectivec/GPBArray.m
@@ -2519,14 +2519,14 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) {
- (id)copyWithZone:(NSZone *)zone {
if (_array == nil) {
- _array = [[NSMutableArray alloc] init];
+ return [[NSMutableArray allocWithZone:zone] init];
}
return [_array copyWithZone:zone];
}
- (id)mutableCopyWithZone:(NSZone *)zone {
if (_array == nil) {
- _array = [[NSMutableArray alloc] init];
+ return [[NSMutableArray allocWithZone:zone] init];
}
return [_array mutableCopyWithZone:zone];
}
diff --git a/objectivec/GPBDictionary.m b/objectivec/GPBDictionary.m
index fd8bd1ce..1c67c680 100644
--- a/objectivec/GPBDictionary.m
+++ b/objectivec/GPBDictionary.m
@@ -13579,22 +13579,26 @@ void GPBDictionaryReadEntry(id mapDictionary,
- (id)copyWithZone:(NSZone *)zone {
if (_dictionary == nil) {
- _dictionary = [[NSMutableDictionary alloc] init];
+ return [[NSMutableDictionary allocWithZone:zone] init];
}
return [_dictionary copyWithZone:zone];
}
- (id)mutableCopyWithZone:(NSZone *)zone {
if (_dictionary == nil) {
- _dictionary = [[NSMutableDictionary alloc] init];
+ return [[NSMutableDictionary allocWithZone:zone] init];
}
return [_dictionary mutableCopyWithZone:zone];
}
+// Not really needed, but subscripting is likely common enough it doesn't hurt
+// to ensure it goes directly to the real NSMutableDictionary.
- (id)objectForKeyedSubscript:(id)key {
return [_dictionary objectForKeyedSubscript:key];
}
+// Not really needed, but subscripting is likely common enough it doesn't hurt
+// to ensure it goes directly to the real NSMutableDictionary.
- (void)setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key {
if (_dictionary == nil) {
_dictionary = [[NSMutableDictionary alloc] init];
diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m
index 4a6f0612..9660f1ed 100644
--- a/objectivec/GPBMessage.m
+++ b/objectivec/GPBMessage.m
@@ -1023,9 +1023,11 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
if (arrayOrMap) {
if (field.fieldType == GPBFieldTypeRepeated) {
if (GPBFieldDataTypeIsObject(field)) {
- GPBAutocreatedArray *autoArray = arrayOrMap;
- if (autoArray->_autocreator == self) {
- autoArray->_autocreator = nil;
+ if ([arrayOrMap isKindOfClass:[GPBAutocreatedArray class]]) {
+ GPBAutocreatedArray *autoArray = arrayOrMap;
+ if (autoArray->_autocreator == self) {
+ autoArray->_autocreator = nil;
+ }
}
} else {
// Type doesn't matter, it is a GPB*Array.
@@ -1037,9 +1039,11 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
} else {
if ((field.mapKeyDataType == GPBDataTypeString) &&
GPBFieldDataTypeIsObject(field)) {
- GPBAutocreatedDictionary *autoDict = arrayOrMap;
- if (autoDict->_autocreator == self) {
- autoDict->_autocreator = nil;
+ if ([arrayOrMap isKindOfClass:[GPBAutocreatedDictionary class]]) {
+ GPBAutocreatedDictionary *autoDict = arrayOrMap;
+ if (autoDict->_autocreator == self) {
+ autoDict->_autocreator = nil;
+ }
}
} else {
// Type doesn't matter, it is a GPB*Dictionary.
diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m
index d4538598..68aadb77 100644
--- a/objectivec/GPBUtilities.m
+++ b/objectivec/GPBUtilities.m
@@ -408,9 +408,11 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
if (field.fieldType == GPBFieldTypeRepeated) {
// If the old array was autocreated by us, then clear it.
if (GPBDataTypeIsObject(fieldType)) {
- GPBAutocreatedArray *autoArray = oldValue;
- if (autoArray->_autocreator == self) {
- autoArray->_autocreator = nil;
+ if ([oldValue isKindOfClass:[GPBAutocreatedArray class]]) {
+ GPBAutocreatedArray *autoArray = oldValue;
+ if (autoArray->_autocreator == self) {
+ autoArray->_autocreator = nil;
+ }
}
} else {
// Type doesn't matter, it is a GPB*Array.
@@ -423,9 +425,11 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
// If the old map was autocreated by us, then clear it.
if ((field.mapKeyDataType == GPBDataTypeString) &&
GPBDataTypeIsObject(fieldType)) {
- GPBAutocreatedDictionary *autoDict = oldValue;
- if (autoDict->_autocreator == self) {
- autoDict->_autocreator = nil;
+ if ([oldValue isKindOfClass:[GPBAutocreatedDictionary class]]) {
+ GPBAutocreatedDictionary *autoDict = oldValue;
+ if (autoDict->_autocreator == self) {
+ autoDict->_autocreator = nil;
+ }
}
} else {
// Type doesn't matter, it is a GPB*Dictionary.
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
index 7ce5d54f..919d0076 100644
--- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
@@ -57,6 +57,7 @@
F47476E51D21A524007C7B1A /* Duration.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248D41A92826400BC1EC6 /* Duration.pbobjc.m */; };
F47476E61D21A524007C7B1A /* Timestamp.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248D61A92826400BC1EC6 /* Timestamp.pbobjc.m */; };
F4B51B1E1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4B51B1D1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm */; };
+ F4C4B9E41E1D976300D3B61D /* GPBDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C4B9E21E1D974F00D3B61D /* GPBDictionaryTests.m */; };
F4E675971B21D0000054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675871B21D0000054530B /* Any.pbobjc.m */; };
F4E675991B21D0000054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675891B21D0000054530B /* Api.pbobjc.m */; };
F4E6759B1B21D0000054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758B1B21D0000054530B /* Empty.pbobjc.m */; };
@@ -187,6 +188,7 @@
F4B6B8B21A9CCBDA00892426 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet_PackagePrivate.h; sourceTree = "<group>"; };
F4B6B8B61A9CD1DE00892426 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionInternals.h; sourceTree = "<group>"; };
F4B6B8B81A9CD1DE00892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = "<group>"; };
+ F4C4B9E21E1D974F00D3B61D /* GPBDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDictionaryTests.m; sourceTree = "<group>"; };
F4CF31701B162ED800BD9B06 /* unittest_objc_startup.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc_startup.proto; sourceTree = "<group>"; };
F4E675861B21D0000054530B /* Any.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Any.pbobjc.h; path = google/protobuf/Any.pbobjc.h; sourceTree = "<group>"; };
F4E675871B21D0000054530B /* Any.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Any.pbobjc.m; path = google/protobuf/Any.pbobjc.m; sourceTree = "<group>"; };
@@ -393,6 +395,7 @@
7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */,
5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */,
F4353D1C1AB8822D005A6198 /* GPBDescriptorTests.m */,
+ F4C4B9E21E1D974F00D3B61D /* GPBDictionaryTests.m */,
F4353D2C1AC06F10005A6198 /* GPBDictionaryTests.pddm */,
F4353D2D1AC06F10005A6198 /* GPBDictionaryTests+Bool.m */,
F4353D2E1AC06F10005A6198 /* GPBDictionaryTests+Int32.m */,
@@ -677,6 +680,7 @@
F4353D371AC06F10005A6198 /* GPBDictionaryTests+String.m in Sources */,
F4353D381AC06F10005A6198 /* GPBDictionaryTests+UInt32.m in Sources */,
8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */,
+ F4C4B9E41E1D976300D3B61D /* GPBDictionaryTests.m in Sources */,
8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */,
8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */,
8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */,
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
index 5f599719..64fc45c0 100644
--- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
@@ -65,6 +65,7 @@
F47476E91D21A537007C7B1A /* Duration.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248DE1A929C7D00BC1EC6 /* Duration.pbobjc.m */; };
F47476EA1D21A537007C7B1A /* Timestamp.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248E01A929C7D00BC1EC6 /* Timestamp.pbobjc.m */; };
F4B51B1C1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */; };
+ F4C4B9E71E1D97BF00D3B61D /* GPBDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */; };
F4E675D01B21D1620054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675B71B21D1440054530B /* Any.pbobjc.m */; };
F4E675D11B21D1620054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675B91B21D1440054530B /* Api.pbobjc.m */; };
F4E675D21B21D1620054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675BC1B21D1440054530B /* Empty.pbobjc.m */; };
@@ -209,6 +210,7 @@
F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet_PackagePrivate.h; sourceTree = "<group>"; };
F4B6B8B31A9CD1C600892426 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionInternals.h; sourceTree = "<group>"; };
F4B6B8B51A9CD1C600892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = "<group>"; };
+ F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDictionaryTests.m; sourceTree = "<group>"; };
F4CF31711B162EF500BD9B06 /* unittest_objc_startup.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc_startup.proto; sourceTree = "<group>"; };
F4E675B61B21D1440054530B /* Any.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Any.pbobjc.h; path = google/protobuf/Any.pbobjc.h; sourceTree = "<group>"; };
F4E675B71B21D1440054530B /* Any.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Any.pbobjc.m; path = google/protobuf/Any.pbobjc.m; sourceTree = "<group>"; };
@@ -431,6 +433,7 @@
7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */,
5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */,
F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */,
+ F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */,
F4353D3A1AC06F31005A6198 /* GPBDictionaryTests.pddm */,
F4353D3B1AC06F31005A6198 /* GPBDictionaryTests+Bool.m */,
F4353D3C1AC06F31005A6198 /* GPBDictionaryTests+Int32.m */,
@@ -773,6 +776,7 @@
F4353D451AC06F31005A6198 /* GPBDictionaryTests+String.m in Sources */,
F4353D461AC06F31005A6198 /* GPBDictionaryTests+UInt32.m in Sources */,
8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */,
+ F4C4B9E71E1D97BF00D3B61D /* GPBDictionaryTests.m in Sources */,
8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */,
8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */,
8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */,
diff --git a/objectivec/Tests/GPBArrayTests.m b/objectivec/Tests/GPBArrayTests.m
index 0fb15e40..31f75501 100644
--- a/objectivec/Tests/GPBArrayTests.m
+++ b/objectivec/Tests/GPBArrayTests.m
@@ -32,6 +32,7 @@
#import <XCTest/XCTest.h>
#import "GPBArray.h"
+#import "GPBArray_PackagePrivate.h"
#import "GPBTestUtilities.h"
@@ -3436,3 +3437,175 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) {
}
@end
+
+#pragma mark - GPBAutocreatedArray Tests
+
+// These are hand written tests to double check some behaviors of the
+// GPBAutocreatedArray.
+
+// NOTE: GPBAutocreatedArray is private to the library, users of the library
+// should never have to directly deal with this class.
+
+@interface GPBAutocreatedArrayTests : XCTestCase
+@end
+
+@implementation GPBAutocreatedArrayTests
+
+- (void)testEquality {
+ GPBAutocreatedArray *array = [[GPBAutocreatedArray alloc] init];
+
+ XCTAssertTrue([array isEqual:@[]]);
+ XCTAssertTrue([array isEqualToArray:@[]]);
+
+ XCTAssertFalse([array isEqual:@[ @"foo" ]]);
+ XCTAssertFalse([array isEqualToArray:@[ @"foo" ]]);
+
+ [array addObject:@"foo"];
+
+ XCTAssertFalse([array isEqual:@[]]);
+ XCTAssertFalse([array isEqualToArray:@[]]);
+ XCTAssertTrue([array isEqual:@[ @"foo" ]]);
+ XCTAssertTrue([array isEqualToArray:@[ @"foo" ]]);
+ XCTAssertFalse([array isEqual:@[ @"bar" ]]);
+ XCTAssertFalse([array isEqualToArray:@[ @"bar" ]]);
+
+ GPBAutocreatedArray *array2 = [[GPBAutocreatedArray alloc] init];
+
+ XCTAssertFalse([array isEqual:array2]);
+ XCTAssertFalse([array isEqualToArray:array2]);
+
+ [array2 addObject:@"bar"];
+ XCTAssertFalse([array isEqual:array2]);
+ XCTAssertFalse([array isEqualToArray:array2]);
+
+ [array2 replaceObjectAtIndex:0 withObject:@"foo"];
+ XCTAssertTrue([array isEqual:array2]);
+ XCTAssertTrue([array isEqualToArray:array2]);
+
+ [array2 release];
+ [array release];
+}
+
+- (void)testCopy {
+ {
+ GPBAutocreatedArray *array = [[GPBAutocreatedArray alloc] init];
+
+ NSArray *cpy = [array copy];
+ XCTAssertTrue(cpy != array); // Ptr compare
+ XCTAssertTrue([cpy isKindOfClass:[NSArray class]]);
+ XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertEqual(cpy.count, (NSUInteger)0);
+
+ NSArray *cpy2 = [array copy];
+ XCTAssertTrue(cpy2 != array); // Ptr compare
+ // Can't compare cpy and cpy2 because NSArray has a singleton empty
+ // array it uses, so the ptrs are the same.
+ XCTAssertTrue([cpy2 isKindOfClass:[NSArray class]]);
+ XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertEqual(cpy2.count, (NSUInteger)0);
+
+ [cpy2 release];
+ [cpy release];
+ [array release];
+ }
+
+ {
+ GPBAutocreatedArray *array = [[GPBAutocreatedArray alloc] init];
+
+ NSMutableArray *cpy = [array mutableCopy];
+ XCTAssertTrue(cpy != array); // Ptr compare
+ XCTAssertTrue([cpy isKindOfClass:[NSMutableArray class]]);
+ XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertEqual(cpy.count, (NSUInteger)0);
+
+ NSMutableArray *cpy2 = [array mutableCopy];
+ XCTAssertTrue(cpy2 != array); // Ptr compare
+ XCTAssertTrue(cpy2 != cpy); // Ptr compare
+ XCTAssertTrue([cpy2 isKindOfClass:[NSMutableArray class]]);
+ XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertEqual(cpy2.count, (NSUInteger)0);
+
+ [cpy2 release];
+ [cpy release];
+ [array release];
+ }
+
+ {
+ GPBAutocreatedArray *array = [[GPBAutocreatedArray alloc] init];
+ [array addObject:@"foo"];
+ [array addObject:@"bar"];
+
+ NSArray *cpy = [array copy];
+ XCTAssertTrue(cpy != array); // Ptr compare
+ XCTAssertTrue([cpy isKindOfClass:[NSArray class]]);
+ XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertEqual(cpy.count, (NSUInteger)2);
+ XCTAssertEqualObjects(cpy[0], @"foo");
+ XCTAssertEqualObjects(cpy[1], @"bar");
+
+ NSArray *cpy2 = [array copy];
+ XCTAssertTrue(cpy2 != array); // Ptr compare
+ XCTAssertTrue(cpy2 != cpy); // Ptr compare
+ XCTAssertTrue([cpy2 isKindOfClass:[NSArray class]]);
+ XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertEqual(cpy2.count, (NSUInteger)2);
+ XCTAssertEqualObjects(cpy2[0], @"foo");
+ XCTAssertEqualObjects(cpy2[1], @"bar");
+
+ [cpy2 release];
+ [cpy release];
+ [array release];
+ }
+
+ {
+ GPBAutocreatedArray *array = [[GPBAutocreatedArray alloc] init];
+ [array addObject:@"foo"];
+ [array addObject:@"bar"];
+
+ NSMutableArray *cpy = [array mutableCopy];
+ XCTAssertTrue(cpy != array); // Ptr compare
+ XCTAssertTrue([cpy isKindOfClass:[NSArray class]]);
+ XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertEqual(cpy.count, (NSUInteger)2);
+ XCTAssertEqualObjects(cpy[0], @"foo");
+ XCTAssertEqualObjects(cpy[1], @"bar");
+
+ NSMutableArray *cpy2 = [array mutableCopy];
+ XCTAssertTrue(cpy2 != array); // Ptr compare
+ XCTAssertTrue(cpy2 != cpy); // Ptr compare
+ XCTAssertTrue([cpy2 isKindOfClass:[NSArray class]]);
+ XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertEqual(cpy2.count, (NSUInteger)2);
+ XCTAssertEqualObjects(cpy2[0], @"foo");
+ XCTAssertEqualObjects(cpy2[1], @"bar");
+
+ [cpy2 release];
+ [cpy release];
+ [array release];
+ }
+}
+
+- (void)testIndexedSubscriptSupport {
+ // The base NSArray/NSMutableArray behaviors for *IndexedSubscript methods
+ // should still work via the methods that one has to override to make an
+ // NSMutableArray subclass. i.e. - this should "just work" and if these
+ // crash/fail, then something is wrong in how NSMutableArray is subclassed.
+
+ GPBAutocreatedArray *array = [[GPBAutocreatedArray alloc] init];
+
+ [array addObject:@"foo"];
+ [array addObject:@"bar"];
+ XCTAssertEqual(array.count, (NSUInteger)2);
+ XCTAssertEqualObjects(array[0], @"foo");
+ XCTAssertEqualObjects(array[1], @"bar");
+ array[0] = @"foo2";
+ array[2] = @"baz";
+ XCTAssertEqual(array.count, (NSUInteger)3);
+ XCTAssertEqualObjects(array[0], @"foo2");
+ XCTAssertEqualObjects(array[1], @"bar");
+ XCTAssertEqualObjects(array[2], @"baz");
+
+ [array release];
+}
+
+@end
diff --git a/objectivec/Tests/GPBDictionaryTests.m b/objectivec/Tests/GPBDictionaryTests.m
new file mode 100644
index 00000000..52b4b328
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests.m
@@ -0,0 +1,186 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 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.
+
+#import <Foundation/Foundation.h>
+#import <XCTest/XCTest.h>
+
+#import "GPBDictionary.h"
+#import "GPBDictionary_PackagePrivate.h"
+
+#import "GPBTestUtilities.h"
+
+#pragma mark - GPBAutocreatedDictionary Tests
+
+// These are hand written tests to double check some behaviors of the
+// GPBAutocreatedDictionary. The GPBDictionary+[type]Tests files are generate
+// tests.
+
+// NOTE: GPBAutocreatedDictionary is private to the library, users of the
+// library should never have to directly deal with this class.
+
+@interface GPBAutocreatedDictionaryTests : XCTestCase
+@end
+
+@implementation GPBAutocreatedDictionaryTests
+
+- (void)testEquality {
+ GPBAutocreatedDictionary *dict = [[GPBAutocreatedDictionary alloc] init];
+
+ XCTAssertTrue([dict isEqual:@{}]);
+ XCTAssertTrue([dict isEqualToDictionary:@{}]);
+
+ XCTAssertFalse([dict isEqual:@{ @"foo" : @"bar" }]);
+ XCTAssertFalse([dict isEqualToDictionary:@{ @"foo" : @"bar" }]);
+
+ [dict setObject:@"bar" forKey:@"foo"];
+
+ XCTAssertFalse([dict isEqual:@{}]);
+ XCTAssertFalse([dict isEqualToDictionary:@{}]);
+ XCTAssertTrue([dict isEqual:@{ @"foo" : @"bar" }]);
+ XCTAssertTrue([dict isEqualToDictionary:@{ @"foo" : @"bar" }]);
+ XCTAssertFalse([dict isEqual:@{ @"bar" : @"baz" }]);
+ XCTAssertFalse([dict isEqualToDictionary:@{ @"bar" : @"baz" }]);
+
+ GPBAutocreatedDictionary *dict2 = [[GPBAutocreatedDictionary alloc] init];
+
+ XCTAssertFalse([dict isEqual:dict2]);
+ XCTAssertFalse([dict isEqualToDictionary:dict2]);
+
+ [dict2 setObject:@"mumble" forKey:@"foo"];
+ XCTAssertFalse([dict isEqual:dict2]);
+ XCTAssertFalse([dict isEqualToDictionary:dict2]);
+
+ [dict2 setObject:@"bar" forKey:@"foo"];
+ XCTAssertTrue([dict isEqual:dict2]);
+ XCTAssertTrue([dict isEqualToDictionary:dict2]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testCopy {
+ {
+ GPBAutocreatedDictionary *dict = [[GPBAutocreatedDictionary alloc] init];
+
+ NSDictionary *cpy = [dict copy];
+ XCTAssertTrue(cpy != dict); // Ptr compare
+ XCTAssertTrue([cpy isKindOfClass:[NSDictionary class]]);
+ XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedDictionary class]]);
+ XCTAssertEqual(cpy.count, (NSUInteger)0);
+
+ NSDictionary *cpy2 = [dict copy];
+ XCTAssertTrue(cpy2 != dict); // Ptr compare
+ XCTAssertTrue(cpy2 != cpy); // Ptr compare
+ XCTAssertTrue([cpy2 isKindOfClass:[NSDictionary class]]);
+ XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedDictionary class]]);
+ XCTAssertEqual(cpy2.count, (NSUInteger)0);
+
+ [cpy2 release];
+ [cpy release];
+ [dict release];
+ }
+
+ {
+ GPBAutocreatedDictionary *dict = [[GPBAutocreatedDictionary alloc] init];
+
+ NSMutableDictionary *cpy = [dict mutableCopy];
+ XCTAssertTrue(cpy != dict); // Ptr compare
+ XCTAssertTrue([cpy isKindOfClass:[NSMutableDictionary class]]);
+ XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedDictionary class]]);
+ XCTAssertEqual(cpy.count, (NSUInteger)0);
+
+ NSMutableDictionary *cpy2 = [dict mutableCopy];
+ XCTAssertTrue(cpy2 != dict); // Ptr compare
+ XCTAssertTrue(cpy2 != cpy); // Ptr compare
+ XCTAssertTrue([cpy2 isKindOfClass:[NSMutableDictionary class]]);
+ XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedDictionary class]]);
+ XCTAssertEqual(cpy2.count, (NSUInteger)0);
+
+ [cpy2 release];
+ [cpy release];
+ [dict release];
+ }
+
+ {
+ GPBAutocreatedDictionary *dict = [[GPBAutocreatedDictionary alloc] init];
+ dict[@"foo"] = @"bar";
+ dict[@"baz"] = @"mumble";
+
+ NSDictionary *cpy = [dict copy];
+ XCTAssertTrue(cpy != dict); // Ptr compare
+ XCTAssertTrue([cpy isKindOfClass:[NSDictionary class]]);
+ XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedDictionary class]]);
+ XCTAssertEqual(cpy.count, (NSUInteger)2);
+ XCTAssertEqualObjects(cpy[@"foo"], @"bar");
+ XCTAssertEqualObjects(cpy[@"baz"], @"mumble");
+
+ NSDictionary *cpy2 = [dict copy];
+ XCTAssertTrue(cpy2 != dict); // Ptr compare
+ XCTAssertTrue(cpy2 != cpy); // Ptr compare
+ XCTAssertTrue([cpy2 isKindOfClass:[NSDictionary class]]);
+ XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedDictionary class]]);
+ XCTAssertEqual(cpy2.count, (NSUInteger)2);
+ XCTAssertEqualObjects(cpy2[@"foo"], @"bar");
+ XCTAssertEqualObjects(cpy2[@"baz"], @"mumble");
+
+ [cpy2 release];
+ [cpy release];
+ [dict release];
+ }
+
+ {
+ GPBAutocreatedDictionary *dict = [[GPBAutocreatedDictionary alloc] init];
+ dict[@"foo"] = @"bar";
+ dict[@"baz"] = @"mumble";
+
+ NSMutableDictionary *cpy = [dict mutableCopy];
+ XCTAssertTrue(cpy != dict); // Ptr compare
+ XCTAssertTrue([cpy isKindOfClass:[NSMutableDictionary class]]);
+ XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedDictionary class]]);
+ XCTAssertEqual(cpy.count, (NSUInteger)2);
+ XCTAssertEqualObjects(cpy[@"foo"], @"bar");
+ XCTAssertEqualObjects(cpy[@"baz"], @"mumble");
+
+ NSMutableDictionary *cpy2 = [dict mutableCopy];
+ XCTAssertTrue(cpy2 != dict); // Ptr compare
+ XCTAssertTrue(cpy2 != cpy); // Ptr compare
+ XCTAssertTrue([cpy2 isKindOfClass:[NSMutableDictionary class]]);
+ XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedDictionary class]]);
+ XCTAssertEqual(cpy2.count, (NSUInteger)2);
+ XCTAssertEqualObjects(cpy2[@"foo"], @"bar");
+ XCTAssertEqualObjects(cpy2[@"baz"], @"mumble");
+
+ [cpy2 release];
+ [cpy release];
+ [dict release];
+ }
+}
+
+@end
diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m
index a3c5a6b4..c15535c5 100644
--- a/objectivec/Tests/GPBMessageTests.m
+++ b/objectivec/Tests/GPBMessageTests.m
@@ -1082,6 +1082,20 @@
[repeatedStringArray release];
}
+- (void)testSetOverAutocreatedArrayAndSetAgain {
+ // Ensure when dealing with replacing an array it is handled being either
+ // an autocreated one or a straight NSArray.
+
+ // The real test here is that nothing crashes while doing the work.
+ TestAllTypes *message = [TestAllTypes message];
+ [message.repeatedStringArray addObject:@"foo"];
+ XCTAssertEqual(message.repeatedStringArray_Count, (NSUInteger)1);
+ message.repeatedStringArray = [NSMutableArray arrayWithObjects:@"bar", @"bar2", nil];
+ XCTAssertEqual(message.repeatedStringArray_Count, (NSUInteger)2);
+ message.repeatedStringArray = [NSMutableArray arrayWithObject:@"baz"];
+ XCTAssertEqual(message.repeatedStringArray_Count, (NSUInteger)1);
+}
+
- (void)testReplaceAutocreatedArray {
// Replacing array should orphan the old one and cause its creator to become
// visible.
@@ -1281,6 +1295,23 @@
[strToStr release];
}
+- (void)testSetOverAutocreatedMapAndSetAgain {
+ // Ensure when dealing with replacing a map it is handled being either
+ // an autocreated one or a straight NSDictionary.
+
+ // The real test here is that nothing crashes while doing the work.
+ TestRecursiveMessageWithRepeatedField *message =
+ [TestRecursiveMessageWithRepeatedField message];
+ message.strToStr[@"foo"] = @"bar";
+ XCTAssertEqual(message.strToStr_Count, (NSUInteger)1);
+ message.strToStr =
+ [NSMutableDictionary dictionaryWithObjectsAndKeys:@"bar", @"key1", @"baz", @"key2", nil];
+ XCTAssertEqual(message.strToStr_Count, (NSUInteger)2);
+ message.strToStr =
+ [NSMutableDictionary dictionaryWithObject:@"baz" forKey:@"mumble"];
+ XCTAssertEqual(message.strToStr_Count, (NSUInteger)1);
+}
+
- (void)testReplaceAutocreatedMap {
// Replacing map should orphan the old one and cause its creator to become
// visible.
diff --git a/php/src/Google/Protobuf/Internal/InputStream.php b/php/src/Google/Protobuf/Internal/InputStream.php
index 6d6c74e9..c5a76d5d 100644
--- a/php/src/Google/Protobuf/Internal/InputStream.php
+++ b/php/src/Google/Protobuf/Internal/InputStream.php
@@ -160,40 +160,59 @@ class InputStream
*/
public function readVarint64(&$var)
{
- $high = 0;
- $low = 0;
$count = 0;
- $b = 0;
-
- do {
- if ($this->current === $this->buffer_end) {
- return false;
- }
- if ($count === self::MAX_VARINT_BYTES) {
- return false;
- }
- $b = ord($this->buffer[$this->current]);
- $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);
if (PHP_INT_SIZE == 4) {
+ $high = 0;
+ $low = 0;
+ $b = 0;
+
+ do {
+ if ($this->current === $this->buffer_end) {
+ return false;
+ }
+ if ($count === self::MAX_VARINT_BYTES) {
+ return false;
+ }
+ $b = ord($this->buffer[$this->current]);
+ $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 = combineInt32ToInt64($high, $low);
} else {
- $var = ($high & 0xFFFFFFFF) << 32 |
- ($low & 0xFFFFFFFF);
+ $result = 0;
+ $shift = 0;
+
+ do {
+ if ($this->current === $this->buffer_end) {
+ return false;
+ }
+ if ($count === self::MAX_VARINT_BYTES) {
+ return false;
+ }
+
+ $byte = ord($this->buffer[$this->current]);
+ $result |= ($byte & 0x7f) << $shift;
+ $shift += 7;
+ $this->advance(1);
+ $count += 1;
+ } while ($byte > 0x7f);
+
+ $var = $result;
}
+
return true;
}
diff --git a/php/tests/php_implementation_test.php b/php/tests/php_implementation_test.php
index 4f626f1c..6b922a9b 100644
--- a/php/tests/php_implementation_test.php
+++ b/php/tests/php_implementation_test.php
@@ -366,6 +366,36 @@ class ImplementationTest extends TestBase
$this->assertSame(32768, $var);
}
$this->assertFalse($input->readVarint64($var));
+
+ // Read 64 testing
+ if (PHP_INT_SIZE > 4) {
+ $testVals = array(
+ '10' => '0a000000000000000000',
+ '100' => '64000000000000000000',
+ '800' => 'a0060000000000000000',
+ '6400' => '80320000000000000000',
+ '70400' => '80a60400000000000000',
+ '774400' => '80a22f00000000000000',
+ '9292800' => '8098b704000000000000',
+ '74342400' => '80c0b923000000000000',
+ '743424000' => '8080bfe2020000000000',
+ '8177664000' => '8080b5bb1e0000000000',
+ '65421312000' => '8080a8dbf30100000000',
+ '785055744000' => '8080e0c7ec1600000000',
+ '9420668928000' => '808080dd969202000000',
+ '103627358208000' => '808080fff9c717000000',
+ '1139900940288000' => '808080f5bd9783020000',
+ '13678811283456000' => '808080fce699a6180000',
+ '109430490267648000' => '808080e0b7ceb1c20100',
+ '984874412408832000' => '808080e0f5c1bed50d00',
+ );
+
+ foreach ($testVals as $original => $encoded) {
+ $input = new InputStream(hex2bin($encoded));
+ $this->assertTrue($input->readVarint64($var));
+ $this->assertSame($original, $var);
+ }
+ }
}
public function testReadVarint32()
diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py
index c5f73dc1..ff3e6d30 100755
--- a/python/google/protobuf/internal/decoder.py
+++ b/python/google/protobuf/internal/decoder.py
@@ -131,9 +131,12 @@ def _VarintDecoder(mask, result_type):
return DecodeVarint
-def _SignedVarintDecoder(mask, result_type):
+def _SignedVarintDecoder(bits, result_type):
"""Like _VarintDecoder() but decodes signed values."""
+ signbit = 1 << (bits - 1)
+ mask = (1 << bits) - 1
+
def DecodeVarint(buffer, pos):
result = 0
shift = 0
@@ -142,11 +145,8 @@ def _SignedVarintDecoder(mask, result_type):
result |= ((b & 0x7f) << shift)
pos += 1
if not (b & 0x80):
- if result > 0x7fffffffffffffff:
- result -= (1 << 64)
- result |= ~mask
- else:
- result &= mask
+ result &= mask
+ result = (result ^ signbit) - signbit
result = result_type(result)
return (result, pos)
shift += 7
@@ -159,11 +159,11 @@ def _SignedVarintDecoder(mask, result_type):
# (e.g. the C++ implementation) simpler.
_DecodeVarint = _VarintDecoder((1 << 64) - 1, long)
-_DecodeSignedVarint = _SignedVarintDecoder((1 << 64) - 1, long)
+_DecodeSignedVarint = _SignedVarintDecoder(64, long)
# Use these versions for values which must be limited to 32 bits.
_DecodeVarint32 = _VarintDecoder((1 << 32) - 1, int)
-_DecodeSignedVarint32 = _SignedVarintDecoder((1 << 32) - 1, int)
+_DecodeSignedVarint32 = _SignedVarintDecoder(32, int)
def ReadTag(buffer, pos):
diff --git a/src/Makefile.am b/src/Makefile.am
index 37204ea0..8807effd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -57,7 +57,8 @@ clean-local:
CLEANFILES = $(protoc_outputs) unittest_proto_middleman \
testzip.jar testzip.list testzip.proto testzip.zip \
no_warning_test.cc \
- google/protobuf/compiler/js/well_known_types_embed.cc
+ google/protobuf/compiler/js/well_known_types_embed.cc \
+ js_embed$(EXEEXT)
MAINTAINERCLEANFILES = \
Makefile.in
@@ -484,13 +485,16 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/csharp/csharp_wrapper_field.cc \
google/protobuf/compiler/csharp/csharp_wrapper_field.h
-bin_PROGRAMS = protoc js_embed
+bin_PROGRAMS = protoc
protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la
protoc_SOURCES = google/protobuf/compiler/main.cc
# The special JS code for the well-known types is linked into the compiler via
-# well_known_types_embed.cc, which is generated from .js source files.
-js_embed_SOURCES = google/protobuf/compiler/js/embed.cc
+# well_known_types_embed.cc, which is generated from .js source files. We have
+# to build the js_embed binary using $(CXX_FOR_BUILD) so that it is executable
+# on the build machine in a cross-compilation setup.
+js_embed$(EXEEXT): $(srcdir)/google/protobuf/compiler/js/embed.cc
+ $(CXX_FOR_BUILD) -o $@ $<
js_well_known_types_sources = \
google/protobuf/compiler/js/well_known_types/any.js \
google/protobuf/compiler/js/well_known_types/struct.js \
@@ -572,6 +576,7 @@ EXTRA_DIST = \
google/protobuf/package_info.h \
google/protobuf/io/package_info.h \
google/protobuf/util/package_info.h \
+ google/protobuf/compiler/js/embed.cc \
google/protobuf/compiler/ruby/ruby_generated_code.proto \
google/protobuf/compiler/ruby/ruby_generated_code_pb.rb \
google/protobuf/compiler/package_info.h \
diff --git a/src/google/protobuf/arena_nc_test.py b/src/google/protobuf/arena_nc_test.py
deleted file mode 100644
index 56a7dd05..00000000
--- a/src/google/protobuf/arena_nc_test.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#! /usr/bin/env python
-#
-# 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.
-
-"""Negative compilation unit tests for arena API."""
-
-import unittest
-
-from google3.testing.pybase import fake_target_util
-from google3.testing.pybase import unittest
-
-
-class ArenaNcTest(unittest.TestCase):
-
- def testCompilerErrors(self):
- """Runs a list of tests to verify compiler error messages."""
-
- # Defines a list of test specs, where each element is a tuple
- # (test name, list of regexes for matching the compiler errors).
- test_specs = [
- ('ARENA_PRIVATE_CONSTRUCTOR',
- [r'calling a protected constructor']),
- ('SANITY', None)]
-
- fake_target_util.AssertCcCompilerErrors(
- self, # The current test case.
- 'google3/google/protobuf/arena_nc', # The fake target file.
- 'arena_nc.o', # The sub-target to build.
- test_specs # List of test specifications.
- )
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index d8fda59c..9cfd6ec6 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -289,6 +289,18 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"classname", message_generators_[i]->classname_);
}
+ for (int i = 0; i < message_generators_.size(); i++) {
+ message_generators_[i]->index_in_metadata_ = i;
+ }
+ for (int i = 0; i < enum_generators_.size(); i++) {
+ enum_generators_[i]->index_in_metadata_ = i;
+ }
+ if (HasGenericServices(file_, options_)) {
+ for (int i = 0; i < service_generators_.size(); i++) {
+ service_generators_[i]->index_in_metadata_ = i;
+ }
+ }
+
if (HasDescriptorMethods(file_, options_)) {
printer->Print(
"\n"
@@ -313,17 +325,8 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
}
for (int i = 0; i < message_generators_.size(); i++) {
- message_generators_[i]->index_in_metadata_ = i;
message_generators_[i]->GenerateDescriptorDeclarations(printer);
}
- for (int i = 0; i < enum_generators_.size(); i++) {
- enum_generators_[i]->index_in_metadata_ = i;
- }
- if (HasGenericServices(file_, options_)) {
- for (int i = 0; i < service_generators_.size(); i++) {
- service_generators_[i]->index_in_metadata_ = i;
- }
- }
printer->Print(
"\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 2b71acb5..2d3d5640 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -1661,18 +1661,6 @@ void MessageGenerator::
GenerateClassMethods(io::Printer* printer) {
if (IsMapEntryMessage(descriptor_)) return;
- // mutable_unknown_fields wrapper function for LazyStringOutputStream
- // callback.
- if (PreserveUnknownFields(descriptor_) &&
- !UseUnknownFieldSet(descriptor_->file(), options_)) {
- printer->Print(
- "static ::std::string* MutableUnknownFieldsFor$classname$(\n"
- " $classname$* ptr) {\n"
- " return ptr->mutable_unknown_fields();\n"
- "}\n"
- "\n",
- "classname", classname_);
- }
if (IsAnyMessage(descriptor_)) {
printer->Print(
"void $classname$::PackFrom(const ::google::protobuf::Message& message) {\n"
@@ -2936,8 +2924,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
// on the CodedOutputStream.
printer->Print(
" ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n"
- " NewPermanentCallback(\n"
- " &MutableUnknownFieldsFor$classname$, this));\n"
+ " ::google::protobuf::NewPermanentCallback(&_internal_metadata_,\n"
+ " &::google::protobuf::internal::InternalMetadataWithArenaLite::mutable_unknown_fields));\n"
" ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n"
" &unknown_fields_string, false);\n",
"classname", classname_);
diff --git a/src/google/protobuf/compiler/js/embed.cc b/src/google/protobuf/compiler/js/embed.cc
index d04fea2e..57d38237 100644
--- a/src/google/protobuf/compiler/js/embed.cc
+++ b/src/google/protobuf/compiler/js/embed.cc
@@ -48,7 +48,7 @@ static char ToDecimalDigit(int num) {
static std::string CEscape(const std::string& str) {
std::string dest;
- for (int i = 0; i < str.size(); ++i) {
+ for (size_t i = 0; i < str.size(); ++i) {
unsigned char ch = str[i];
switch (ch) {
case '\n': dest += "\\n"; break;
@@ -98,7 +98,7 @@ static void AddFile(const char* name, std::basic_ostream<char>* out) {
int main(int argc, char *argv[]) {
std::cout << "#include "
- "\"google/protobuf/compiler/js/well_known_types_embed.h\"\n";
+ "<google/protobuf/compiler/js/well_known_types_embed.h>\n";
std::cout << "struct FileToc well_known_types_js[] = {\n";
for (int i = 1; i < argc; i++) {
diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc
index e6571f6f..727ed090 100755
--- a/src/google/protobuf/compiler/js/js_generator.cc
+++ b/src/google/protobuf/compiler/js/js_generator.cc
@@ -1865,7 +1865,19 @@ void Generator::GenerateClass(const GeneratorOptions& options,
// objects.
GenerateClassDeserializeBinary(options, printer, desc);
GenerateClassSerializeBinary(options, printer, desc);
+ }
+
+ // Recurse on nested types. These must come *before* the extension-field
+ // info generation in GenerateClassRegistration so that extensions that
+ // reference nested types proceed the definitions of the nested types.
+ for (int i = 0; i < desc->enum_type_count(); i++) {
+ GenerateEnum(options, printer, desc->enum_type(i));
+ }
+ for (int i = 0; i < desc->nested_type_count(); i++) {
+ GenerateClass(options, printer, desc->nested_type(i));
+ }
+ if (!NamespaceOnly(desc)) {
GenerateClassRegistration(options, printer, desc);
GenerateClassFields(options, printer, desc);
if (IsExtendable(desc) && desc->full_name() != "google.protobuf.bridge.MessageSet") {
@@ -1879,13 +1891,6 @@ void Generator::GenerateClass(const GeneratorOptions& options,
}
}
- // Recurse on nested types.
- for (int i = 0; i < desc->enum_type_count(); i++) {
- GenerateEnum(options, printer, desc->enum_type(i));
- }
- for (int i = 0; i < desc->nested_type_count(); i++) {
- GenerateClass(options, printer, desc->nested_type(i));
- }
}
void Generator::GenerateClassConstructor(const GeneratorOptions& options,
diff --git a/src/google/protobuf/stubs/callback.h b/src/google/protobuf/stubs/callback.h
index bbd507a8..9ec04979 100644
--- a/src/google/protobuf/stubs/callback.h
+++ b/src/google/protobuf/stubs/callback.h
@@ -346,6 +346,29 @@ struct InternalConstRef {
typedef const base_type& type;
};
+template<typename R, typename T>
+class MethodResultCallback_0_0 : public ResultCallback<R> {
+ public:
+ typedef R (T::*MethodType)();
+ MethodResultCallback_0_0(T* object, MethodType method, bool self_deleting)
+ : object_(object),
+ method_(method),
+ self_deleting_(self_deleting) {}
+ ~MethodResultCallback_0_0() {}
+
+ R Run() {
+ bool needs_delete = self_deleting_;
+ R result = (object_->*method_)();
+ if (needs_delete) delete this;
+ return result;
+ }
+
+ private:
+ T* object_;
+ MethodType method_;
+ bool self_deleting_;
+};
+
template <typename R, typename T, typename P1, typename P2, typename P3,
typename P4, typename P5, typename A1, typename A2>
class MethodResultCallback_5_2 : public ResultCallback2<R, A1, A2> {
@@ -520,6 +543,13 @@ inline ResultCallback1<R, A1>* NewPermanentCallback(
function, false, p1);
}
+// See MethodResultCallback_0_0
+template <typename R, typename T1, typename T2>
+inline ResultCallback<R>* NewPermanentCallback(
+ T1* object, R (T2::*function)()) {
+ return new internal::MethodResultCallback_0_0<R, T1>(object, function, false);
+}
+
// See MethodResultCallback_5_2
template <typename R, typename T, typename P1, typename P2, typename P3,
typename P4, typename P5, typename A1, typename A2>