Merge branch master into v3.0.0-beta-2

pull/1068/head
Feng Xiao 9 years ago
commit d217808417
  1. 1
      Makefile.am
  2. 2
      cmake/CMakeLists.txt
  3. 9
      csharp/src/AddressBook/Addressbook.cs
  4. 10
      csharp/src/Google.Protobuf.Conformance/Conformance.cs
  5. 43
      csharp/src/Google.Protobuf.Conformance/Program.cs
  6. 14
      csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
  7. 2
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs
  8. 2
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs
  9. 20
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
  10. 70
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
  11. 8
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
  12. 23
      csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
  13. 10
      csharp/src/Google.Protobuf/Google.Protobuf.csproj
  14. 57
      csharp/src/Google.Protobuf/Google.Protobuf.nuspec
  15. 54
      csharp/src/Google.Protobuf/JsonFormatter.cs
  16. 44
      csharp/src/Google.Protobuf/Reflection/Descriptor.cs
  17. 2
      csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
  18. 6
      csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
  19. 2
      csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs
  20. 2
      csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs
  21. 2
      csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs
  22. 2
      csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs
  23. 6
      csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
  24. 2
      csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs
  25. 10
      csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
  26. 18
      csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs
  27. 4
      csharp/src/Google.Protobuf/packages.config
  28. 5
      examples/add_person.go
  29. 46
      examples/list_people.go
  30. 24
      examples/list_people_test.go
  31. 329
      objectivec/GPBCodedInputStream.m
  32. 17
      objectivec/GPBCodedInputStream_PackagePrivate.h
  33. 14
      objectivec/GPBMessage.m
  34. 7
      objectivec/GPBMessage_PackagePrivate.h
  35. 28
      objectivec/GPBRootObject.m
  36. 4
      objectivec/GPBUtilities.m
  37. 4
      objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
  38. 4
      objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
  39. 6
      objectivec/Tests/GPBCodedInputStreamTests.m
  40. 513
      objectivec/Tests/GPBStringTests.m
  41. 2
      src/google/protobuf/compiler/csharp/csharp_message.cc
  42. 31
      src/google/protobuf/descriptor.cc

@ -475,7 +475,6 @@ objectivec_EXTRA_DIST= \
objectivec/Tests/GPBMessageTests.m \
objectivec/Tests/GPBObjectiveCPlusPlusTest.mm \
objectivec/Tests/GPBPerfTests.m \
objectivec/Tests/GPBStringTests.m \
objectivec/Tests/GPBSwiftTests.swift \
objectivec/Tests/GPBTestUtilities.h \
objectivec/Tests/GPBTestUtilities.m \

@ -115,6 +115,8 @@ else (protobuf_BUILD_SHARED_LIBS)
endif (protobuf_BUILD_SHARED_LIBS)
if (MSVC)
# Build with multiple processes
add_definitions(/MP)
add_definitions(/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305)
string(REPLACE "/" "\\" PROTOBUF_SOURCE_WIN32_PATH ${protobuf_SOURCE_DIR})
string(REPLACE "/" "\\" PROTOBUF_BINARY_WIN32_PATH ${protobuf_BINARY_DIR})

@ -43,6 +43,9 @@ namespace Google.Protobuf.Examples.AddressBook {
}
#region Messages
/// <summary>
/// [START messages]
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class Person : pb::IMessage<Person> {
private static readonly pb::MessageParser<Person> _parser = new pb::MessageParser<Person>(() => new Person());
@ -143,7 +146,7 @@ namespace Google.Protobuf.Examples.AddressBook {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -302,7 +305,7 @@ namespace Google.Protobuf.Examples.AddressBook {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -426,7 +429,7 @@ namespace Google.Protobuf.Examples.AddressBook {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -284,7 +284,7 @@ namespace Conformance {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -532,7 +532,7 @@ namespace Conformance {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1544,7 +1544,7 @@ namespace Conformance {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -2343,7 +2343,7 @@ namespace Conformance {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -2471,7 +2471,7 @@ namespace Conformance {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -31,6 +31,7 @@
#endregion
using Conformance;
using Google.Protobuf.Reflection;
using System;
using System.IO;
@ -47,16 +48,17 @@ namespace Google.Protobuf.Conformance
// This way we get the binary streams instead of readers/writers.
var input = new BinaryReader(Console.OpenStandardInput());
var output = new BinaryWriter(Console.OpenStandardOutput());
var typeRegistry = TypeRegistry.FromMessages(TestAllTypes.Descriptor);
int count = 0;
while (RunTest(input, output))
while (RunTest(input, output, typeRegistry))
{
count++;
}
Console.Error.WriteLine("Received EOF after {0} tests", count);
}
private static bool RunTest(BinaryReader input, BinaryWriter output)
private static bool RunTest(BinaryReader input, BinaryWriter output, TypeRegistry typeRegistry)
{
int? size = ReadInt32(input);
if (size == null)
@ -69,7 +71,7 @@ namespace Google.Protobuf.Conformance
throw new EndOfStreamException("Read " + inputData.Length + " bytes of data when expecting " + size);
}
ConformanceRequest request = ConformanceRequest.Parser.ParseFrom(inputData);
ConformanceResponse response = PerformRequest(request);
ConformanceResponse response = PerformRequest(request, typeRegistry);
byte[] outputData = response.ToByteArray();
output.Write(outputData.Length);
output.Write(outputData);
@ -77,30 +79,33 @@ namespace Google.Protobuf.Conformance
return true;
}
private static ConformanceResponse PerformRequest(ConformanceRequest request)
private static ConformanceResponse PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry)
{
TestAllTypes message;
switch (request.PayloadCase)
try
{
case ConformanceRequest.PayloadOneofCase.JsonPayload:
return new ConformanceResponse { Skipped = "JSON parsing not implemented in C# yet" };
case ConformanceRequest.PayloadOneofCase.ProtobufPayload:
try
{
switch (request.PayloadCase)
{
case ConformanceRequest.PayloadOneofCase.JsonPayload:
var parser = new JsonParser(new JsonParser.Settings(20, typeRegistry));
message = parser.Parse<TestAllTypes>(request.JsonPayload);
break;
case ConformanceRequest.PayloadOneofCase.ProtobufPayload:
message = TestAllTypes.Parser.ParseFrom(request.ProtobufPayload);
}
catch (InvalidProtocolBufferException e)
{
return new ConformanceResponse { ParseError = e.Message };
}
break;
default:
throw new Exception("Unsupported request payload: " + request.PayloadCase);
break;
default:
throw new Exception("Unsupported request payload: " + request.PayloadCase);
}
}
catch (InvalidProtocolBufferException e)
{
return new ConformanceResponse { ParseError = e.Message };
}
switch (request.RequestedOutputFormat)
{
case global::Conformance.WireFormat.JSON:
return new ConformanceResponse { JsonPayload = JsonFormatter.Default.Format(message) };
var formatter = new JsonFormatter(new JsonFormatter.Settings(false, typeRegistry));
return new ConformanceResponse { JsonPayload = formatter.Format(message) };
case global::Conformance.WireFormat.PROTOBUF:
return new ConformanceResponse { ProtobufPayload = message.ToByteString() };
default:

@ -425,7 +425,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -633,7 +633,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -741,7 +741,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -851,7 +851,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1121,7 +1121,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1318,7 +1318,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1427,7 +1427,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -110,7 +110,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -96,7 +96,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -126,7 +126,7 @@ namespace UnitTest.Issues.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -204,7 +204,7 @@ namespace UnitTest.Issues.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -282,7 +282,7 @@ namespace UnitTest.Issues.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -405,7 +405,7 @@ namespace UnitTest.Issues.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -511,7 +511,7 @@ namespace UnitTest.Issues.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -668,7 +668,7 @@ namespace UnitTest.Issues.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -831,7 +831,7 @@ namespace UnitTest.Issues.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -947,7 +947,7 @@ namespace UnitTest.Issues.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1056,7 +1056,7 @@ namespace UnitTest.Issues.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1279,7 +1279,7 @@ namespace UnitTest.Issues.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -927,7 +927,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1600,7 +1600,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1736,7 +1736,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1873,7 +1873,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1980,7 +1980,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -2070,7 +2070,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -2162,7 +2162,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -2291,7 +2291,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -2421,7 +2421,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -2547,7 +2547,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -2669,7 +2669,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -2883,7 +2883,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -3107,7 +3107,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -3278,7 +3278,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -3400,7 +3400,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -3506,7 +3506,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -3608,7 +3608,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -3704,7 +3704,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -3807,7 +3807,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -3913,7 +3913,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -4016,7 +4016,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -4119,7 +4119,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -4222,7 +4222,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -4325,7 +4325,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -4486,7 +4486,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -4780,7 +4780,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -5140,7 +5140,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -5414,7 +5414,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -5554,7 +5554,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -5647,7 +5647,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -5723,7 +5723,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -5799,7 +5799,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -5875,7 +5875,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -5951,7 +5951,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -6027,7 +6027,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -466,7 +466,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1106,7 +1106,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1625,7 +1625,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -2213,7 +2213,7 @@ namespace Google.Protobuf.TestProtos {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -62,5 +62,28 @@ namespace Google.Protobuf.WellKnownTypes
var unpacked = any.Unpack<TestAllTypes>();
Assert.AreEqual(message, unpacked);
}
[Test]
public void ToString_WithValues()
{
var message = SampleMessages.CreateFullTestAllTypes();
var any = Any.Pack(message);
var text = any.ToString();
Assert.That(text, Is.StringContaining("\"@value\": \"" + message.ToByteString().ToBase64() + "\""));
}
[Test]
public void ToString_Empty()
{
var any = new Any();
Assert.AreEqual("{ \"@type\": \"\", \"@value\": \"\" }", any.ToString());
}
[Test]
public void ToString_MessageContainingAny()
{
var message = new TestWellKnownTypes { AnyField = new Any() };
Assert.AreEqual("{ \"anyField\": { \"@type\": \"\", \"@value\": \"\" } }", message.ToString());
}
}
}

@ -16,6 +16,8 @@
<FileAlignment>512</FileAlignment>
<OldToolsVersion>3.5</OldToolsVersion>
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -142,9 +144,17 @@
</ItemGroup>
<ItemGroup>
<None Include="Google.Protobuf.nuspec" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<Import Project="..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets" Condition="Exists('..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<package>
<metadata>
<id>Google.Protobuf</id>
<title>Google Protocol Buffers C#</title>
<summary>C# runtime library for Protocol Buffers - Google's data interchange format.</summary>
<description>See project site for more info.</description>
<version>3.0.0-alpha4</version>
<version>3.0.0-beta2</version>
<authors>Google Inc.</authors>
<owners>protobuf-packages</owners>
<licenseUrl>https://github.com/google/protobuf/blob/master/LICENSE</licenseUrl>
@ -14,24 +14,43 @@
<releaseNotes>C# proto3 support</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>Protocol Buffers Binary Serialization Format Google proto proto3</tags>
<dependencies>
<group targetFramework="dotnet">
<dependency id="System.Collections" version="4.0.0" />
<dependency id="System.Diagnostics.Debug" version="4.0.0" />
<dependency id="System.Globalization" version="4.0.0" />
<dependency id="System.IO" version="4.0.0" />
<dependency id="System.Linq" version="4.0.0" />
<dependency id="System.Linq.Expressions" version="4.0.0" />
<dependency id="System.ObjectModel" version="4.0.0" />
<dependency id="System.Reflection" version="4.0.0" />
<dependency id="System.Runtime" version="4.0.0" />
<dependency id="System.Runtime.Extensions" version="4.0.0" />
<dependency id="System.Text.Encoding" version="4.0.0" />
<dependency id="System.Text.RegularExpressions" version="4.0.0" />
</group>
</dependencies>
</metadata>
<files>
<file src="bin/ReleaseSigned/Google.Protobuf.dll" target="lib/portable-net45+netcore45+wpa81+wp8" />
<file src="bin/ReleaseSigned/Google.Protobuf.pdb" target="lib/portable-net45+netcore45+wpa81+wp8" />
<file src="bin/ReleaseSigned/Google.Protobuf.xml" target="lib/portable-net45+netcore45+wpa81+wp8" />
<file src="**\*.cs" target="src" />
<file src="..\..\..\cmake\Release\protoc.exe" target="tools" />
<file src="..\..\..\src\google\protobuf\any.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\api.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\descriptor.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\duration.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\empty.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\field_mask.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\source_context.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\struct.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\timestamp.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\any.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\type.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\wrappers.proto" target="tools\google\protobuf" />
<file src="bin/ReleaseSigned/Google.Protobuf.pdb" target="lib/portable-net45+netcore45+wpa81+wp8" />
<file src="bin/ReleaseSigned/Google.Protobuf.xml" target="lib/portable-net45+netcore45+wpa81+wp8" />
<file src="bin/ReleaseSigned/Google.Protobuf.dll" target="lib/dotnet" />
<file src="bin/ReleaseSigned/Google.Protobuf.pdb" target="lib/dotnet" />
<file src="bin/ReleaseSigned/Google.Protobuf.xml" target="lib/dotnet" />
<file src="**\*.cs" target="src" />
<file src="..\..\..\cmake\Release\protoc.exe" target="tools" />
<file src="..\..\..\src\google\protobuf\any.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\api.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\descriptor.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\duration.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\empty.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\field_mask.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\source_context.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\struct.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\timestamp.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\any.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\type.proto" target="tools\google\protobuf" />
<file src="..\..\..\src\google\protobuf\wrappers.proto" target="tools\google\protobuf" />
</files>
</package>
</package>

@ -56,17 +56,19 @@ namespace Google.Protobuf
public sealed class JsonFormatter
{
internal const string AnyTypeUrlField = "@type";
internal const string AnyDiagnosticValueField = "@value";
internal const string AnyWellKnownTypeValueField = "value";
private const string TypeUrlPrefix = "type.googleapis.com";
private const string NameValueSeparator = ": ";
private const string PropertySeparator = ", ";
private static JsonFormatter defaultInstance = new JsonFormatter(Settings.Default);
/// <summary>
/// Returns a formatter using the default settings.
/// </summary>
public static JsonFormatter Default { get { return defaultInstance; } }
public static JsonFormatter Default { get; } = new JsonFormatter(Settings.Default);
// A JSON formatter which *only* exists
private static readonly JsonFormatter diagnosticFormatter = new JsonFormatter(Settings.Default);
/// <summary>
/// The JSON representation of the first 160 characters of Unicode.
@ -149,6 +151,29 @@ namespace Google.Protobuf
return builder.ToString();
}
/// <summary>
/// Converts a message to JSON for diagnostic purposes with no extra context.
/// </summary>
/// <remarks>
/// <para>
/// This differs from calling <see cref="Format(IMessage)"/> on the default JSON
/// formatter in its handling of <see cref="Any"/>. As no type registry is available
/// in <see cref="object.ToString"/> calls, the normal way of resolving the type of
/// an <c>Any</c> message cannot be applied. Instead, a JSON property named <c>@value</c>
/// is included with the base64 data from the <see cref="Any.Value"/> property of the message.
/// </para>
/// <para>The value returned by this method is only designed to be used for diagnostic
/// purposes. It may not be parsable by <see cref="JsonParser"/>, and may not be parsable
/// by other Protocol Buffer implementations.</para>
/// </remarks>
/// <param name="message">The message to format for diagnostic purposes.</param>
/// <returns>The diagnostic-only JSON representation of the message</returns>
public static string ToDiagnosticString(IMessage message)
{
Preconditions.CheckNotNull(message, nameof(message));
return diagnosticFormatter.Format(message);
}
private void WriteMessage(StringBuilder builder, IMessage message)
{
if (message == null)
@ -516,6 +541,12 @@ namespace Google.Protobuf
private void WriteAny(StringBuilder builder, IMessage value)
{
if (ReferenceEquals(this, diagnosticFormatter))
{
WriteDiagnosticOnlyAny(builder, value);
return;
}
string typeUrl = (string) value.Descriptor.Fields[Any.TypeUrlFieldNumber].Accessor.GetValue(value);
ByteString data = (ByteString) value.Descriptor.Fields[Any.ValueFieldNumber].Accessor.GetValue(value);
string typeName = GetTypeName(typeUrl);
@ -544,6 +575,23 @@ namespace Google.Protobuf
builder.Append(" }");
}
private void WriteDiagnosticOnlyAny(StringBuilder builder, IMessage value)
{
string typeUrl = (string) value.Descriptor.Fields[Any.TypeUrlFieldNumber].Accessor.GetValue(value);
ByteString data = (ByteString) value.Descriptor.Fields[Any.ValueFieldNumber].Accessor.GetValue(value);
builder.Append("{ ");
WriteString(builder, AnyTypeUrlField);
builder.Append(NameValueSeparator);
WriteString(builder, typeUrl);
builder.Append(PropertySeparator);
WriteString(builder, AnyDiagnosticValueField);
builder.Append(NameValueSeparator);
builder.Append('"');
builder.Append(data.ToBase64());
builder.Append('"');
builder.Append(" }");
}
internal static string GetTypeName(String typeUrl)
{
string[] parts = typeUrl.Split('/');

@ -225,7 +225,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -489,7 +489,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -827,7 +827,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1021,7 +1021,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1162,7 +1162,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1436,7 +1436,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1741,7 +1741,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1872,7 +1872,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -2031,7 +2031,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -2196,7 +2196,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -2404,7 +2404,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -2863,7 +2863,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -3302,7 +3302,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -3596,7 +3596,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -3845,7 +3845,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -3990,7 +3990,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -4121,7 +4121,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -4252,7 +4252,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -4451,7 +4451,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -4653,7 +4653,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -4823,7 +4823,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -5051,7 +5051,7 @@ namespace Google.Protobuf.Reflection {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -165,7 +165,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -230,7 +230,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -503,7 +503,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -783,7 +783,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -164,7 +164,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -94,7 +94,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -221,7 +221,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -105,7 +105,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -136,7 +136,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -361,7 +361,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -555,7 +555,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -175,7 +175,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -230,7 +230,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -522,7 +522,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -910,7 +910,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1098,7 +1098,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1244,7 +1244,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -117,7 +117,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -228,7 +228,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -339,7 +339,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -450,7 +450,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -561,7 +561,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -672,7 +672,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -783,7 +783,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -894,7 +894,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
@ -1005,7 +1005,7 @@ namespace Google.Protobuf.WellKnownTypes {
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NuSpec.ReferenceGenerator" version="1.4.1" targetFramework="portable45-net45+win8+wp8+wpa81" developmentDependency="true" />
</packages>

@ -105,7 +105,10 @@ func main() {
log.Fatalln("Error reading file:", err)
}
}
// [START marshal_proto]
book := &pb.AddressBook{}
// [START_EXCLUDE]
if err := proto.Unmarshal(in, book); err != nil {
log.Fatalln("Failed to parse address book:", err)
}
@ -116,6 +119,7 @@ func main() {
log.Fatalln("Error with address:", err)
}
book.People = append(book.People, addr)
// [END_EXCLUDE]
// Write the new address book back to disk.
out, err := proto.Marshal(book)
@ -125,4 +129,5 @@ func main() {
if err := ioutil.WriteFile(fname, out, 0644); err != nil {
log.Fatalln("Failed to write address book:", err)
}
// [END marshal_proto]
}

@ -11,25 +11,29 @@ import (
pb "github.com/google/protobuf/examples/tutorial"
)
func listPeople(w io.Writer, book *pb.AddressBook) {
for _, p := range book.People {
fmt.Fprintln(w, "Person ID:", p.Id)
fmt.Fprintln(w, " Name:", p.Name)
if p.Email != "" {
fmt.Fprintln(w, " E-mail address:", p.Email)
}
func writePerson(w io.Writer, p *pb.Person) {
fmt.Fprintln(w, "Person ID:", p.Id)
fmt.Fprintln(w, " Name:", p.Name)
if p.Email != "" {
fmt.Fprintln(w, " E-mail address:", p.Email)
}
for _, pn := range p.Phones {
switch pn.Type {
case pb.Person_MOBILE:
fmt.Fprint(w, " Mobile phone #: ")
case pb.Person_HOME:
fmt.Fprint(w, " Home phone #: ")
case pb.Person_WORK:
fmt.Fprint(w, " Work phone #: ")
}
fmt.Fprintln(w, pn.Number)
for _, pn := range p.Phones {
switch pn.Type {
case pb.Person_MOBILE:
fmt.Fprint(w, " Mobile phone #: ")
case pb.Person_HOME:
fmt.Fprint(w, " Home phone #: ")
case pb.Person_WORK:
fmt.Fprint(w, " Work phone #: ")
}
fmt.Fprintln(w, pn.Number)
}
}
func listPeople(w io.Writer, book *pb.AddressBook) {
for _, p := range book.People {
writePerson(w, p)
}
}
@ -41,19 +45,17 @@ func main() {
}
fname := os.Args[1]
// [START unmarshal_proto]
// Read the existing address book.
in, err := ioutil.ReadFile(fname)
if err != nil {
if os.IsNotExist(err) {
fmt.Printf("%s: File not found. Creating new file.\n", fname)
} else {
log.Fatalln("Error reading file:", err)
}
log.Fatalln("Error reading file:", err)
}
book := &pb.AddressBook{}
if err := proto.Unmarshal(in, book); err != nil {
log.Fatalln("Failed to parse address book:", err)
}
// [END unmarshal_proto]
listPeople(os.Stdout, book)
}

@ -8,6 +8,30 @@ import (
pb "github.com/google/protobuf/examples/tutorial"
)
func TestWritePersonWritesPerson(t *testing.T) {
buf := new(bytes.Buffer)
// [START populate_proto]
p := pb.Person{
Id: 1234,
Name: "John Doe",
Email: "jdoe@example.com",
Phones: []*pb.Person_PhoneNumber{
{Number: "555-4321", Type: pb.Person_HOME},
},
}
// [END populate_proto]
writePerson(buf, &p)
got := buf.String()
want := `Person ID: 1234
Name: John Doe
E-mail address: jdoe@example.com
Home phone #: 555-4321
`
if got != want {
t.Errorf("writePerson(%s) =>\n\t%q, want %q", p.String(), got, want)
}
}
func TestListPeopleWritesList(t *testing.T) {
buf := new(bytes.Buffer)
in := pb.AddressBook{[]*pb.Person{

@ -216,7 +216,17 @@ NSString *GPBCodedInputStreamReadRetainedString(
result = @"";
} else {
CheckSize(state, size);
result = GPBCreateGPBStringWithUTF8(&state->bytes[state->bufferPos], size);
result = [[NSString alloc] initWithBytes:&state->bytes[state->bufferPos]
length:size
encoding:NSUTF8StringEncoding];
if (!result) {
result = @"";
#ifdef DEBUG
// https://developers.google.com/protocol-buffers/docs/proto#scalar
NSLog(@"UTF8 failure, is some field type 'string' when it should be "
@"'bytes'?");
#endif
}
state->bufferPos += size;
}
return result;
@ -478,320 +488,3 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state,
}
@end
@implementation GPBString {
@package
CFStringRef string_;
unsigned char *utf8_;
NSUInteger utf8Len_;
// This lock is used to gate access to utf8_. Once GPBStringInitStringValue()
// has been called, string_ will be filled in, and utf8_ will be NULL.
OSSpinLock lock_;
BOOL hasBOM_;
BOOL is7BitAscii_;
}
// Returns true if the passed in bytes are 7 bit ascii.
// This routine needs to be fast.
static bool AreBytesIn7BitASCII(const uint8_t *bytes, NSUInteger len) {
// In the loops below, it's more efficient to collect rather than do
// conditional at every step.
#if __LP64__
// Align bytes. This is especially important in case of 3 byte BOM.
while (len > 0 && ((size_t)bytes & 0x07)) {
if (*bytes++ & 0x80) return false;
len--;
}
while (len >= 32) {
uint64_t val = *(const uint64_t *)bytes;
uint64_t hiBits = (val & 0x8080808080808080ULL);
bytes += 8;
val = *(const uint64_t *)bytes;
hiBits |= (val & 0x8080808080808080ULL);
bytes += 8;
val = *(const uint64_t *)bytes;
hiBits |= (val & 0x8080808080808080ULL);
bytes += 8;
val = *(const uint64_t *)bytes;
if (hiBits | (val & 0x8080808080808080ULL)) return false;
bytes += 8;
len -= 32;
}
while (len >= 16) {
uint64_t val = *(const uint64_t *)bytes;
uint64_t hiBits = (val & 0x8080808080808080ULL);
bytes += 8;
val = *(const uint64_t *)bytes;
if (hiBits | (val & 0x8080808080808080ULL)) return false;
bytes += 8;
len -= 16;
}
while (len >= 8) {
uint64_t val = *(const uint64_t *)bytes;
if (val & 0x8080808080808080ULL) return false;
bytes += 8;
len -= 8;
}
#else // __LP64__
// Align bytes. This is especially important in case of 3 byte BOM.
while (len > 0 && ((size_t)bytes & 0x03)) {
if (*bytes++ & 0x80) return false;
len--;
}
while (len >= 16) {
uint32_t val = *(const uint32_t *)bytes;
uint32_t hiBits = (val & 0x80808080U);
bytes += 4;
val = *(const uint32_t *)bytes;
hiBits |= (val & 0x80808080U);
bytes += 4;
val = *(const uint32_t *)bytes;
hiBits |= (val & 0x80808080U);
bytes += 4;
val = *(const uint32_t *)bytes;
if (hiBits | (val & 0x80808080U)) return false;
bytes += 4;
len -= 16;
}
while (len >= 8) {
uint32_t val = *(const uint32_t *)bytes;
uint32_t hiBits = (val & 0x80808080U);
bytes += 4;
val = *(const uint32_t *)bytes;
if (hiBits | (val & 0x80808080U)) return false;
bytes += 4;
len -= 8;
}
#endif // __LP64__
while (len >= 4) {
uint32_t val = *(const uint32_t *)bytes;
if (val & 0x80808080U) return false;
bytes += 4;
len -= 4;
}
while (len--) {
if (*bytes++ & 0x80) return false;
}
return true;
}
static void GPBStringInitStringValue(GPBString *string) {
OSSpinLockLock(&string->lock_);
GPBStringInitStringValueAlreadyLocked(string);
OSSpinLockUnlock(&string->lock_);
}
static void GPBStringInitStringValueAlreadyLocked(GPBString *string) {
if (string->string_ == NULL && string->utf8_ != NULL) {
// Using kCFAllocatorMalloc for contentsDeallocator, as buffer in
// string->utf8_ is being handed off.
string->string_ = CFStringCreateWithBytesNoCopy(
NULL, string->utf8_, string->utf8Len_, kCFStringEncodingUTF8, false,
kCFAllocatorMalloc);
if (!string->string_) {
#ifdef DEBUG
// https://developers.google.com/protocol-buffers/docs/proto#scalar
NSLog(@"UTF8 failure, is some field type 'string' when it should be "
@"'bytes'?");
#endif
string->string_ = CFSTR("");
string->utf8Len_ = 0;
// On failure, we have to clean up the buffer.
free(string->utf8_);
}
string->utf8_ = NULL;
}
}
GPBString *GPBCreateGPBStringWithUTF8(const void *bytes, NSUInteger length) {
GPBString *result = [[GPBString alloc] initWithBytes:bytes length:length];
return result;
}
- (instancetype)initWithBytes:(const void *)bytes length:(NSUInteger)length {
self = [super init];
if (self) {
utf8_ = malloc(length);
memcpy(utf8_, bytes, length);
utf8Len_ = length;
lock_ = OS_SPINLOCK_INIT;
is7BitAscii_ = AreBytesIn7BitASCII(bytes, length);
if (length >= 3 && memcmp(utf8_, "\xef\xbb\xbf", 3) == 0) {
// We can't just remove the BOM from the string here, because in the case
// where we have > 1 BOM at the beginning of the string, we will remove one,
// and the internal NSString we create will remove the next one, and we will
// end up with a GPBString != NSString issue.
// We also just can't remove all the BOMs because then we would end up with
// potential cases where a GPBString and an NSString made with the same
// UTF8 buffer would in fact be different.
// We record the fact we have a BOM, and use it as necessary to simulate
// what NSString would return for various calls.
hasBOM_ = YES;
#if DEBUG
// Sending BOMs across the line is just wasting bits.
NSLog(@"Bad data? String should not have BOM!");
#endif // DEBUG
}
}
return self;
}
- (void)dealloc {
if (string_ != NULL) {
CFRelease(string_);
}
if (utf8_ != NULL) {
free(utf8_);
}
[super dealloc];
}
// Required NSString overrides.
- (NSUInteger)length {
if (is7BitAscii_) {
return utf8Len_;
} else {
GPBStringInitStringValue(self);
return CFStringGetLength(string_);
}
}
- (unichar)characterAtIndex:(NSUInteger)anIndex {
OSSpinLockLock(&lock_);
if (is7BitAscii_ && utf8_) {
unichar result = utf8_[anIndex];
OSSpinLockUnlock(&lock_);
return result;
} else {
GPBStringInitStringValueAlreadyLocked(self);
OSSpinLockUnlock(&lock_);
return CFStringGetCharacterAtIndex(string_, anIndex);
}
}
// Override a couple of methods that typically want high performance.
- (id)copyWithZone:(NSZone *)zone {
GPBStringInitStringValue(self);
return [(NSString *)string_ copyWithZone:zone];
}
- (id)mutableCopyWithZone:(NSZone *)zone {
GPBStringInitStringValue(self);
return [(NSString *)string_ mutableCopyWithZone:zone];
}
- (NSUInteger)hash {
// Must convert to string here to make sure that the hash is always
// consistent no matter what state the GPBString is in.
GPBStringInitStringValue(self);
return CFHash(string_);
}
- (BOOL)isEqual:(id)object {
if (self == object) {
return YES;
}
if ([object isKindOfClass:[NSString class]]) {
GPBStringInitStringValue(self);
return CFStringCompare(string_, (CFStringRef)object, 0) ==
kCFCompareEqualTo;
}
return NO;
}
- (void)getCharacters:(unichar *)buffer range:(NSRange)aRange {
OSSpinLockLock(&lock_);
if (is7BitAscii_ && utf8_) {
unsigned char *bytes = &(utf8_[aRange.location]);
for (NSUInteger i = 0; i < aRange.length; ++i) {
buffer[i] = bytes[i];
}
OSSpinLockUnlock(&lock_);
} else {
GPBStringInitStringValueAlreadyLocked(self);
OSSpinLockUnlock(&lock_);
CFStringGetCharacters(string_, CFRangeMake(aRange.location, aRange.length),
buffer);
}
}
- (NSUInteger)lengthOfBytesUsingEncoding:(NSStringEncoding)encoding {
if ((encoding == NSUTF8StringEncoding) ||
(encoding == NSASCIIStringEncoding && is7BitAscii_)) {
return utf8Len_ - (hasBOM_ ? 3 : 0);
} else {
GPBStringInitStringValue(self);
return [(NSString *)string_ lengthOfBytesUsingEncoding:encoding];
}
}
- (BOOL)getBytes:(void *)buffer
maxLength:(NSUInteger)maxLength
usedLength:(NSUInteger *)usedLength
encoding:(NSStringEncoding)encoding
options:(NSStringEncodingConversionOptions)options
range:(NSRange)range
remainingRange:(NSRangePointer)remainingRange {
// [NSString getBytes:maxLength:usedLength:encoding:options:range:remainingRange]
// does not return reliable results if the maxLength argument is 0
// (Radar 16385183). Therefore we have special cased it as a slow case so
// that it behaves however Apple intends it to behave. It should be a rare
// case.
//
// [NSString getBytes:maxLength:usedLength:encoding:options:range:remainingRange]
// does not return reliable results if the range is outside of the strings
// length (Radar 16396177). Therefore we have special cased it as a slow
// case so that it behaves however Apple intends it to behave. It should
// be a rare case.
//
// We can optimize the UTF8StringEncoding and NSASCIIStringEncoding with no
// options cases.
if ((options == 0) &&
(encoding == NSUTF8StringEncoding || encoding == NSASCIIStringEncoding) &&
(maxLength != 0) &&
(NSMaxRange(range) <= utf8Len_)) {
// Might be able to optimize it.
OSSpinLockLock(&lock_);
if (is7BitAscii_ && utf8_) {
NSUInteger length = range.length;
length = (length < maxLength) ? length : maxLength;
memcpy(buffer, utf8_ + range.location, length);
if (usedLength) {
*usedLength = length;
}
if (remainingRange) {
remainingRange->location = range.location + length;
remainingRange->length = range.length - length;
}
OSSpinLockUnlock(&lock_);
if (length > 0) {
return YES;
} else {
return NO;
}
} else {
GPBStringInitStringValueAlreadyLocked(self);
OSSpinLockUnlock(&lock_);
}
} else {
GPBStringInitStringValue(self);
}
return [(NSString *)string_ getBytes:buffer
maxLength:maxLength
usedLength:usedLength
encoding:encoding
options:options
range:range
remainingRange:remainingRange];
}
@end

@ -39,19 +39,6 @@
@class GPBUnknownFieldSet;
@class GPBFieldDescriptor;
// GPBString is a string subclass that avoids the overhead of initializing
// a full NSString until it is actually needed. Lots of protocol buffers contain
// strings, and instantiating all of those strings and having them parsed to
// verify correctness when the message was being read was expensive, when many
// of the strings were never being used.
//
// Note for future-self. I tried implementing this using a NSProxy.
// Turned out the performance was horrible in client apps because folks
// like to use libraries like SBJSON that grab characters one at a time.
// The proxy overhead was a killer.
@interface GPBString : NSString
@end
typedef struct GPBCodedInputStreamState {
const uint8_t *bytes;
size_t bufferSize;
@ -92,10 +79,6 @@ typedef struct GPBCodedInputStreamState {
CF_EXTERN_C_BEGIN
// Returns a GPBString with a +1 retain count.
GPBString *GPBCreateGPBStringWithUTF8(const void *bytes, NSUInteger length)
__attribute__((ns_returns_retained));
int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state);
double GPBCodedInputStreamReadDouble(GPBCodedInputStreamState *state);

@ -568,13 +568,13 @@ static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
if (!array) {
// Check again after getting the lock.
OSSpinLockLock(&self->readOnlyMutex_);
dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
if (!array) {
array = CreateArrayForField(field, self);
GPBSetAutocreatedRetainedObjectIvarWithField(self, field, array);
}
OSSpinLockUnlock(&self->readOnlyMutex_);
dispatch_semaphore_signal(self->readOnlySemaphore_);
}
return array;
}
@ -598,13 +598,13 @@ static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
if (!dict) {
// Check again after getting the lock.
OSSpinLockLock(&self->readOnlyMutex_);
dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
if (!dict) {
dict = CreateMapForField(field, self);
GPBSetAutocreatedRetainedObjectIvarWithField(self, field, dict);
}
OSSpinLockUnlock(&self->readOnlyMutex_);
dispatch_semaphore_signal(self->readOnlySemaphore_);
}
return dict;
}
@ -810,7 +810,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
messageStorage_ = (GPBMessage_StoragePtr)(
((uint8_t *)self) + class_getInstanceSize([self class]));
readOnlyMutex_ = OS_SPINLOCK_INIT;
readOnlySemaphore_ = dispatch_semaphore_create(1);
}
return self;
@ -1723,7 +1723,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
}
// Check for an autocreated value.
OSSpinLockLock(&readOnlyMutex_);
dispatch_semaphore_wait(readOnlySemaphore_, DISPATCH_TIME_FOREVER);
value = [autocreatedExtensionMap_ objectForKey:extension];
if (!value) {
// Auto create the message extensions to match normal fields.
@ -1740,7 +1740,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
[value release];
}
OSSpinLockUnlock(&readOnlyMutex_);
dispatch_semaphore_signal(readOnlySemaphore_);
return value;
}

@ -62,7 +62,12 @@ typedef struct GPBMessage_Storage *GPBMessage_StoragePtr;
// by *read* operations such as getters (autocreation of message fields and
// message extensions, not setting of values). Used to guarantee thread safety
// for concurrent reads on the message.
OSSpinLock readOnlyMutex_;
// NOTE: OSSpinLock may seem like a good fit here but Apple engineers have
// pointed out that they are vulnerable to live locking on iOS in cases of
// priority inversion:
// http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/
// https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html
dispatch_semaphore_t readOnlySemaphore_;
}
// Gets an extension value without autocreating the result if not found. (i.e.

@ -31,7 +31,6 @@
#import "GPBRootObject_PackagePrivate.h"
#import <objc/runtime.h>
#import <libkern/OSAtomic.h>
#import <CoreFoundation/CoreFoundation.h>
@ -96,13 +95,19 @@ static CFHashCode GPBRootExtensionKeyHash(const void *value) {
return jenkins_one_at_a_time_hash(key);
}
static OSSpinLock gExtensionSingletonDictionaryLock_ = OS_SPINLOCK_INIT;
// NOTE: OSSpinLock may seem like a good fit here but Apple engineers have
// pointed out that they are vulnerable to live locking on iOS in cases of
// priority inversion:
// http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/
// https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html
static dispatch_semaphore_t gExtensionSingletonDictionarySemaphore;
static CFMutableDictionaryRef gExtensionSingletonDictionary = NULL;
static GPBExtensionRegistry *gDefaultExtensionRegistry = NULL;
+ (void)initialize {
// Ensure the global is started up.
if (!gExtensionSingletonDictionary) {
gExtensionSingletonDictionarySemaphore = dispatch_semaphore_create(1);
CFDictionaryKeyCallBacks keyCallBacks = {
// See description above for reason for using custom dictionary.
0,
@ -134,9 +139,10 @@ static GPBExtensionRegistry *gDefaultExtensionRegistry = NULL;
+ (void)globallyRegisterExtension:(GPBExtensionDescriptor *)field {
const char *key = [field singletonNameC];
OSSpinLockLock(&gExtensionSingletonDictionaryLock_);
dispatch_semaphore_wait(gExtensionSingletonDictionarySemaphore,
DISPATCH_TIME_FOREVER);
CFDictionarySetValue(gExtensionSingletonDictionary, key, field);
OSSpinLockUnlock(&gExtensionSingletonDictionaryLock_);
dispatch_semaphore_signal(gExtensionSingletonDictionarySemaphore);
}
static id ExtensionForName(id self, SEL _cmd) {
@ -166,14 +172,24 @@ static id ExtensionForName(id self, SEL _cmd) {
key[classNameLen] = '_';
memcpy(&key[classNameLen + 1], selName, selNameLen);
key[classNameLen + 1 + selNameLen] = '\0';
OSSpinLockLock(&gExtensionSingletonDictionaryLock_);
// NOTE: Even though this method is called from another C function,
// gExtensionSingletonDictionarySemaphore and gExtensionSingletonDictionary
// will always be initialized. This is because this call flow is just to
// lookup the Extension, meaning the code is calling an Extension class
// message on a Message or Root class. This guarantees that the class was
// initialized and Message classes ensure their Root was also initialized.
NSAssert(gExtensionSingletonDictionary, @"Startup order broken!");
dispatch_semaphore_wait(gExtensionSingletonDictionarySemaphore,
DISPATCH_TIME_FOREVER);
id extension = (id)CFDictionaryGetValue(gExtensionSingletonDictionary, key);
if (extension) {
// The method is getting wired in to the class, so no need to keep it in
// the dictionary.
CFDictionaryRemoveValue(gExtensionSingletonDictionary, key);
}
OSSpinLockUnlock(&gExtensionSingletonDictionaryLock_);
dispatch_semaphore_signal(gExtensionSingletonDictionarySemaphore);
return extension;
}

@ -411,7 +411,7 @@ id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
return field.defaultValue.valueMessage;
}
OSSpinLockLock(&self->readOnlyMutex_);
dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
GPBMessage *result = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
if (!result) {
// For non repeated messages, create the object, set it and return it.
@ -420,7 +420,7 @@ id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
result = GPBCreateMessageWithAutocreator(field.msgClass, self, field);
GPBSetAutocreatedRetainedObjectIvarWithField(self, field, result);
}
OSSpinLockUnlock(&self->readOnlyMutex_);
dispatch_semaphore_signal(self->readOnlySemaphore_);
return result;
}

@ -28,7 +28,6 @@
8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */; };
8B96157514CA019D00A2AC0B /* Descriptor.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */; };
8BA9364518DA5F4C0056FA2A /* GPBStringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BA9364418DA5F4B0056FA2A /* GPBStringTests.m */; };
8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */; };
8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */; };
8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */; };
@ -158,7 +157,6 @@
8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBARCUnittestProtos.m; sourceTree = "<group>"; };
8B96157214C8B06000A2AC0B /* GPBDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDescriptor.h; sourceTree = "<group>"; };
8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptor.m; sourceTree = "<group>"; };
8BA9364418DA5F4B0056FA2A /* GPBStringTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBStringTests.m; sourceTree = "<group>"; };
8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_lite.proto; path = ../../src/google/protobuf/unittest_lite.proto; sourceTree = "<group>"; };
8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = "<group>"; };
@ -419,7 +417,6 @@
F4487C7E1AAF62CD00531423 /* GPBMessageTests+Serialization.m */,
F4B51B1D1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm */,
F41C175C1833D3310064ED4D /* GPBPerfTests.m */,
8BA9364418DA5F4B0056FA2A /* GPBStringTests.m */,
8B4248BA1A8C256A00BC1EC6 /* GPBSwiftTests.swift */,
7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */,
7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */,
@ -689,7 +686,6 @@
F41C175D1833D3310064ED4D /* GPBPerfTests.m in Sources */,
F4353D341AC06F10005A6198 /* GPBDictionaryTests+Bool.m in Sources */,
F4487C831AAF6AB300531423 /* GPBMessageTests+Merge.m in Sources */,
8BA9364518DA5F4C0056FA2A /* GPBStringTests.m in Sources */,
8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */,
F4353D371AC06F10005A6198 /* GPBDictionaryTests+String.m in Sources */,
F4353D381AC06F10005A6198 /* GPBDictionaryTests+UInt32.m in Sources */,

@ -36,7 +36,6 @@
8B9A5EB41831993600A9D33B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B9A5EB31831993600A9D33B /* AppDelegate.m */; };
8B9A5EB61831993600A9D33B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8B9A5EB51831993600A9D33B /* Images.xcassets */; };
8B9A5EEC18330A0F00A9D33B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B9A5E9F1831913D00A9D33B /* UIKit.framework */; };
8BA9364518DA5F4C0056FA2A /* GPBStringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BA9364418DA5F4B0056FA2A /* GPBStringTests.m */; };
8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */; };
8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */; };
8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */; };
@ -179,7 +178,6 @@
8B9A5EAD1831993600A9D33B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
8B9A5EB31831993600A9D33B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
8B9A5EB51831993600A9D33B /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
8BA9364418DA5F4B0056FA2A /* GPBStringTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBStringTests.m; sourceTree = "<group>"; };
8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_lite.proto; path = ../../src/google/protobuf/unittest_lite.proto; sourceTree = "<group>"; };
8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = "<group>"; };
@ -457,7 +455,6 @@
F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */,
F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */,
F41C175C1833D3310064ED4D /* GPBPerfTests.m */,
8BA9364418DA5F4B0056FA2A /* GPBStringTests.m */,
8B4248B31A8BD96E00BC1EC6 /* GPBSwiftTests.swift */,
7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */,
7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */,
@ -785,7 +782,6 @@
F41C175D1833D3310064ED4D /* GPBPerfTests.m in Sources */,
F4353D421AC06F31005A6198 /* GPBDictionaryTests+Bool.m in Sources */,
F4487C851AAF6AC500531423 /* GPBMessageTests+Merge.m in Sources */,
8BA9364518DA5F4C0056FA2A /* GPBStringTests.m in Sources */,
8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */,
F4353D451AC06F31005A6198 /* GPBDictionaryTests+String.m in Sources */,
F4353D461AC06F31005A6198 /* GPBDictionaryTests+UInt32.m in Sources */,

@ -266,6 +266,9 @@
}
// Verifies fix for b/10315336.
// Note: Now that there isn't a custom string class under the hood, this test
// isn't as critical, but it does cover bad input and if a custom class is added
// again, it will help validate that class' handing of bad utf8.
- (void)testReadMalformedString {
NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
GPBCodedOutputStream* output =
@ -276,7 +279,7 @@
[output writeRawVarint32:tag];
[output writeRawVarint32:5];
// Create an invalid utf-8 byte array.
uint8_t bytes[5] = {0xc2, 0xf2};
uint8_t bytes[] = {0xc2, 0xf2, 0x0, 0x0, 0x0};
[output writeRawData:[NSData dataWithBytes:bytes length:sizeof(bytes)]];
[output flush];
@ -286,6 +289,7 @@
TestAllTypes* message = [TestAllTypes parseFromCodedInputStream:input
extensionRegistry:nil
error:NULL];
XCTAssertNotNil(message);
// Make sure we can read string properties twice without crashing.
XCTAssertEqual([message.defaultString length], (NSUInteger)0);
XCTAssertEqualObjects(@"", message.defaultString);

@ -1,513 +0,0 @@
// 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.
#import <XCTest/XCTest.h>
#import "GPBCodedInputStream_PackagePrivate.h"
#import "GPBTestUtilities.h"
@interface TestClass : NSObject
@property(nonatomic, retain) NSString *foo;
@end
@implementation TestClass
@synthesize foo;
@end
@interface GPBStringTests : XCTestCase {
NSMutableArray *nsStrings_;
NSMutableArray *gpbStrings_;
}
@end
@implementation GPBStringTests
- (void)setUp {
[super setUp];
const char *strings[] = {
"ascii string",
"non-ascii string \xc3\xa9", // e with acute accent
"\xe2\x99\xa1", // White Heart
"mix \xe2\x99\xa4 string", // White Spade
// Decomposed forms from http://www.unicode.org/reports/tr15/
// 1.2 Singletons
"\xe2\x84\xa8 = A\xcc\x8a = \xc3\x85", "\xe2\x84\xa6 = \xce\xa9",
// 1.2 Canonical Composites
"A\xcc\x8a = \xc3\x85",
"o\xcc\x82 = \xc3\xb4",
// 1.2 Multiple Combining Marks
"s\xcc\xa3\xcc\x87 = \xe1\xb9\xa9",
"\xe1\xb8\x8b\xcc\xa3 = d\xcc\xa3\xcc\x87 = \xe1\xb8\x8d \xcc\x87",
"q\xcc\x87\xcc\xa3 = q\xcc\xa3\xcc\x87",
// BOM
"\xEF\xBB\xBF String with BOM",
"String with \xEF\xBB\xBF in middle",
"String with end bom \xEF\xBB\xBF",
"\xEF\xBB\xBF\xe2\x99\xa1", // BOM White Heart
"\xEF\xBB\xBF\xEF\xBB\xBF String with Two BOM",
// Supplementary Plane
"\xf0\x9d\x84\x9e", // MUSICAL SYMBOL G CLEF
// Tags
"\xf3\xa0\x80\x81", // Language Tag
// Variation Selectors
"\xf3\xa0\x84\x80", // VARIATION SELECTOR-17
// Specials
"\xef\xbb\xbf\xef\xbf\xbd\xef\xbf\xbf",
// Left To Right/Right To Left
// http://unicode.org/reports/tr9/
// Hello! <RTL marker>!Merhaba<LTR marker>
"Hello! \xE2\x80\x8F!\xd9\x85\xd8\xb1\xd8\xad\xd8\xa8\xd8\xa7\xE2\x80\x8E",
"\xE2\x80\x8E LTR At Start",
"LTR At End\xE2\x80\x8E",
"\xE2\x80\x8F RTL At Start",
"RTL At End\xE2\x80\x8F",
"\xE2\x80\x8E\xE2\x80\x8E Double LTR \xE2\x80\x8E\xE2\x80\x8E",
"\xE2\x80\x8F\xE2\x80\x8F Double RTL \xE2\x80\x8F\xE2\x80\x8F",
"\xE2\x80\x8F\xE2\x80\x8E LTR-RTL LTR-RTL \xE2\x80\x8E\xE2\x80\x8F",
};
size_t stringsSize = GPBARRAYSIZE(strings);
size_t numberUnicodeStrings = 17375;
nsStrings_ = [[NSMutableArray alloc]
initWithCapacity:stringsSize + numberUnicodeStrings];
gpbStrings_ = [[NSMutableArray alloc]
initWithCapacity:stringsSize + numberUnicodeStrings];
for (size_t i = 0; i < stringsSize; ++i) {
size_t length = strlen(strings[i]);
NSString *nsString = [[NSString alloc] initWithBytes:strings[i]
length:length
encoding:NSUTF8StringEncoding];
[nsStrings_ addObject:nsString];
[nsString release];
GPBString *gpbString = GPBCreateGPBStringWithUTF8(strings[i], length);
[gpbStrings_ addObject:gpbString];
[gpbString release];
}
// Generate all UTF8 characters in a variety of strings
// UTF8-1 - 1 Byte UTF 8 chars
int length = 0x7F + 1;
char *buffer = (char *)calloc(length, 1);
for (int i = 0; i < length; ++i) {
buffer[i] = (char)i;
}
NSString *nsString = [[NSString alloc] initWithBytes:buffer
length:length
encoding:NSUTF8StringEncoding];
[nsStrings_ addObject:nsString];
[nsString release];
GPBString *gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
[gpbStrings_ addObject:gpbString];
[gpbString release];
// UTF8-2 - 2 Byte UTF 8 chars
int pointLength = 0xbf - 0x80 + 1;
length = pointLength * 2;
buffer = (char *)calloc(length, 1);
for (int i = 0xc2; i <= 0xdf; ++i) {
char *bufferPtr = buffer;
for (int j = 0x80; j <= 0xbf; ++j) {
(*bufferPtr++) = (char)i;
(*bufferPtr++) = (char)j;
}
nsString = [[NSString alloc] initWithBytes:buffer
length:length
encoding:NSUTF8StringEncoding];
[nsStrings_ addObject:nsString];
[nsString release];
gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
[gpbStrings_ addObject:gpbString];
[gpbString release];
}
free(buffer);
// UTF8-3 - 3 Byte UTF 8 chars
length = pointLength * 3;
buffer = (char *)calloc(length, 1);
for (int i = 0xa0; i <= 0xbf; ++i) {
char *bufferPtr = buffer;
for (int j = 0x80; j <= 0xbf; ++j) {
(*bufferPtr++) = (char)0xE0;
(*bufferPtr++) = (char)i;
(*bufferPtr++) = (char)j;
}
nsString = [[NSString alloc] initWithBytes:buffer
length:length
encoding:NSUTF8StringEncoding];
[nsStrings_ addObject:nsString];
[nsString release];
gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
[gpbStrings_ addObject:gpbString];
[gpbString release];
}
for (int i = 0xe1; i <= 0xec; ++i) {
for (int j = 0x80; j <= 0xbf; ++j) {
char *bufferPtr = buffer;
for (int k = 0x80; k <= 0xbf; ++k) {
(*bufferPtr++) = (char)i;
(*bufferPtr++) = (char)j;
(*bufferPtr++) = (char)k;
}
nsString = [[NSString alloc] initWithBytes:buffer
length:length
encoding:NSUTF8StringEncoding];
[nsStrings_ addObject:nsString];
[nsString release];
gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
[gpbStrings_ addObject:gpbString];
[gpbString release];
}
}
for (int i = 0x80; i <= 0x9f; ++i) {
char *bufferPtr = buffer;
for (int j = 0x80; j <= 0xbf; ++j) {
(*bufferPtr++) = (char)0xED;
(*bufferPtr++) = (char)i;
(*bufferPtr++) = (char)j;
}
nsString = [[NSString alloc] initWithBytes:buffer
length:length
encoding:NSUTF8StringEncoding];
[nsStrings_ addObject:nsString];
[nsString release];
gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
[gpbStrings_ addObject:gpbString];
[gpbString release];
}
for (int i = 0xee; i <= 0xef; ++i) {
for (int j = 0x80; j <= 0xbf; ++j) {
char *bufferPtr = buffer;
for (int k = 0x80; k <= 0xbf; ++k) {
(*bufferPtr++) = (char)i;
(*bufferPtr++) = (char)j;
(*bufferPtr++) = (char)k;
}
nsString = [[NSString alloc] initWithBytes:buffer
length:length
encoding:NSUTF8StringEncoding];
[nsStrings_ addObject:nsString];
[nsString release];
gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
[gpbStrings_ addObject:gpbString];
[gpbString release];
}
}
free(buffer);
// UTF8-4 - 4 Byte UTF 8 chars
length = pointLength * 4;
buffer = (char *)calloc(length, 1);
for (int i = 0x90; i <= 0xbf; ++i) {
for (int j = 0x80; j <= 0xbf; ++j) {
char *bufferPtr = buffer;
for (int k = 0x80; k <= 0xbf; ++k) {
(*bufferPtr++) = (char)0xF0;
(*bufferPtr++) = (char)i;
(*bufferPtr++) = (char)j;
(*bufferPtr++) = (char)k;
}
nsString = [[NSString alloc] initWithBytes:buffer
length:length
encoding:NSUTF8StringEncoding];
[nsStrings_ addObject:nsString];
[nsString release];
gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
[gpbStrings_ addObject:gpbString];
[gpbString release];
}
}
for (int i = 0xf1; i <= 0xf3; ++i) {
for (int j = 0x80; j <= 0xbf; ++j) {
for (int k = 0x80; k <= 0xbf; ++k) {
char *bufferPtr = buffer;
for (int m = 0x80; m <= 0xbf; ++m) {
(*bufferPtr++) = (char)i;
(*bufferPtr++) = (char)j;
(*bufferPtr++) = (char)k;
(*bufferPtr++) = (char)m;
}
nsString = [[NSString alloc] initWithBytes:buffer
length:length
encoding:NSUTF8StringEncoding];
[nsStrings_ addObject:nsString];
[nsString release];
gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
[gpbStrings_ addObject:gpbString];
[gpbString release];
}
}
}
for (int i = 0x80; i <= 0x8f; ++i) {
for (int j = 0x80; j <= 0xbf; ++j) {
char *bufferPtr = buffer;
for (int k = 0x80; k <= 0xbf; ++k) {
(*bufferPtr++) = (char)0xF4;
(*bufferPtr++) = (char)i;
(*bufferPtr++) = (char)j;
(*bufferPtr++) = (char)k;
}
nsString = [[NSString alloc] initWithBytes:buffer
length:length
encoding:NSUTF8StringEncoding];
[nsStrings_ addObject:nsString];
[nsString release];
gpbString = GPBCreateGPBStringWithUTF8(buffer, length);
[gpbStrings_ addObject:gpbString];
[gpbString release];
}
}
free(buffer);
}
- (void)tearDown {
[nsStrings_ release];
[gpbStrings_ release];
[super tearDown];
}
- (void)testLength {
size_t i = 0;
for (NSString *nsString in nsStrings_) {
GPBString *gpbString = gpbStrings_[i];
XCTAssertEqual([nsString length], [gpbString length], @"%@ %@", nsString,
gpbString);
++i;
}
}
- (void)testLengthOfBytesUsingEncoding {
NSStringEncoding encodings[] = {
NSUTF8StringEncoding,
NSASCIIStringEncoding,
NSISOLatin1StringEncoding,
NSMacOSRomanStringEncoding,
NSUTF16StringEncoding,
NSUTF32StringEncoding,
};
for (size_t j = 0; j < GPBARRAYSIZE(encodings); ++j) {
NSStringEncoding testEncoding = encodings[j];
size_t i = 0;
for (NSString *nsString in nsStrings_) {
GPBString *gpbString = gpbStrings_[i];
XCTAssertEqual([nsString lengthOfBytesUsingEncoding:testEncoding],
[gpbString lengthOfBytesUsingEncoding:testEncoding],
@"%@ %@", nsString, gpbString);
++i;
}
}
}
- (void)testHash {
size_t i = 0;
for (NSString *nsString in nsStrings_) {
GPBString *gpbString = gpbStrings_[i];
XCTAssertEqual([nsString hash], [gpbString hash], @"%@ %@", nsString,
gpbString);
++i;
}
}
- (void)testEquality {
size_t i = 0;
for (NSString *nsString in nsStrings_) {
GPBString *gpbString = gpbStrings_[i];
XCTAssertEqualObjects(nsString, gpbString);
++i;
}
}
- (void)testCharacterAtIndex {
size_t i = 0;
for (NSString *nsString in nsStrings_) {
GPBString *gpbString = gpbStrings_[i];
NSUInteger length = [nsString length];
for (size_t j = 0; j < length; ++j) {
unichar nsChar = [nsString characterAtIndex:j];
unichar pbChar = [gpbString characterAtIndex:j];
XCTAssertEqual(nsChar, pbChar, @"%@ %@ %zu", nsString, gpbString, j);
}
++i;
}
}
- (void)testCopy {
size_t i = 0;
for (NSString *nsString in nsStrings_) {
GPBString *gpbString = [[gpbStrings_[i] copy] autorelease];
XCTAssertEqualObjects(nsString, gpbString);
++i;
}
}
- (void)testMutableCopy {
size_t i = 0;
for (NSString *nsString in nsStrings_) {
GPBString *gpbString = [[gpbStrings_[i] mutableCopy] autorelease];
XCTAssertEqualObjects(nsString, gpbString);
++i;
}
}
- (void)testGetBytes {
// Do an attempt at a reasonably exhaustive test of get bytes.
// Get bytes with options other than 0 should always fall through to Apple
// code so we don't bother testing that path.
size_t i = 0;
char pbBuffer[256];
char nsBuffer[256];
int count = 0;
for (NSString *nsString in nsStrings_) {
GPBString *gpbString = gpbStrings_[i];
for (int j = 0; j < 100; ++j) {
// [NSString getBytes:maxLength:usedLength:encoding:options:range:remainingRange]
// does not return reliable results if the maxLength argument is 0,
// or range is 0,0.
// Radar 16385183
NSUInteger length = [nsString length];
NSUInteger maxBufferCount = (arc4random() % (length + 3)) + 1;
NSUInteger rangeStart = arc4random() % length;
NSUInteger rangeLength = arc4random() % (length - rangeStart);
NSRange range = NSMakeRange(rangeStart, rangeLength);
NSStringEncoding encodings[] = {
NSASCIIStringEncoding,
NSUTF8StringEncoding,
NSUTF16StringEncoding,
};
for (size_t k = 0; k < GPBARRAYSIZE(encodings); ++k) {
NSStringEncoding encoding = encodings[k];
NSUInteger pbUsedBufferCount = 0;
NSUInteger nsUsedBufferCount = 0;
NSRange pbLeftOver = NSMakeRange(0, 0);
NSRange nsLeftOver = NSMakeRange(0, 0);
BOOL pbGotBytes = [gpbString getBytes:pbBuffer
maxLength:maxBufferCount
usedLength:&pbUsedBufferCount
encoding:encoding
options:0
range:range
remainingRange:&pbLeftOver];
BOOL nsGotBytes = [nsString getBytes:nsBuffer
maxLength:maxBufferCount
usedLength:&nsUsedBufferCount
encoding:encoding
options:0
range:range
remainingRange:&nsLeftOver];
XCTAssertEqual(
(bool)pbGotBytes, (bool)nsGotBytes,
@"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "
@"Used: %tu, %tu LeftOver %@, %@)",
count, gpbString, nsString, encoding, maxBufferCount,
NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,
NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));
XCTAssertEqual(
pbUsedBufferCount, nsUsedBufferCount,
@"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "
@"Used: %tu, %tu LeftOver %@, %@)",
count, gpbString, nsString, encoding, maxBufferCount,
NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,
NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));
XCTAssertEqual(
pbLeftOver.location, nsLeftOver.location,
@"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "
@"Used: %tu, %tu LeftOver %@, %@)",
count, gpbString, nsString, encoding, maxBufferCount,
NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,
NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));
XCTAssertEqual(
pbLeftOver.length, nsLeftOver.length,
@"PB %d '%@' vs '%@' Encoding:%tu MaxLength: %tu Range: %@ "
@"Used: %tu, %tu LeftOver %@, %@)",
count, gpbString, nsString, encoding, maxBufferCount,
NSStringFromRange(range), pbUsedBufferCount, nsUsedBufferCount,
NSStringFromRange(pbLeftOver), NSStringFromRange(nsLeftOver));
++count;
}
}
++i;
}
}
- (void)testLengthAndGetBytes {
// This test exists as an attempt to ferret out a bug.
// http://b/13516532
size_t i = 0;
char pbBuffer[256];
char nsBuffer[256];
for (NSString *nsString in nsStrings_) {
GPBString *gpbString = gpbStrings_[i++];
NSUInteger nsLength =
[nsString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSUInteger pbLength =
[gpbString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
XCTAssertEqual(nsLength, pbLength, @"%@ %@", nsString, gpbString);
NSUInteger pbUsedBufferCount = 0;
NSUInteger nsUsedBufferCount = 0;
NSRange pbLeftOver = NSMakeRange(0, 0);
NSRange nsLeftOver = NSMakeRange(0, 0);
NSRange range = NSMakeRange(0, [gpbString length]);
BOOL pbGotBytes = [gpbString getBytes:pbBuffer
maxLength:sizeof(pbBuffer)
usedLength:&pbUsedBufferCount
encoding:NSUTF8StringEncoding
options:0
range:range
remainingRange:&pbLeftOver];
BOOL nsGotBytes = [nsString getBytes:nsBuffer
maxLength:sizeof(nsBuffer)
usedLength:&nsUsedBufferCount
encoding:NSUTF8StringEncoding
options:0
range:range
remainingRange:&nsLeftOver];
XCTAssertTrue(pbGotBytes, @"%@", gpbString);
XCTAssertTrue(nsGotBytes, @"%@", nsString);
XCTAssertEqual(pbUsedBufferCount, pbLength, @"%@", gpbString);
XCTAssertEqual(nsUsedBufferCount, nsLength, @"%@", nsString);
}
}
@end

@ -353,7 +353,7 @@ void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
printer->Print(
"public override string ToString() {\n"
" return pb::JsonFormatter.Default.Format(this);\n"
" return pb::JsonFormatter.ToDiagnosticString(this);\n"
"}\n\n");
}

@ -560,7 +560,7 @@ class FileDescriptorTables {
~FileDescriptorTables();
// Empty table, used with placeholder files.
static const FileDescriptorTables kEmpty;
inline static const FileDescriptorTables& GetEmptyInstance();
// -----------------------------------------------------------------
// Finding items.
@ -665,7 +665,32 @@ FileDescriptorTables::FileDescriptorTables()
FileDescriptorTables::~FileDescriptorTables() {}
const FileDescriptorTables FileDescriptorTables::kEmpty;
namespace {
FileDescriptorTables* file_descriptor_tables_ = NULL;
GOOGLE_PROTOBUF_DECLARE_ONCE(file_descriptor_tables_once_init_);
void DeleteFileDescriptorTables() {
delete file_descriptor_tables_;
file_descriptor_tables_ = NULL;
}
void InitFileDescriptorTables() {
file_descriptor_tables_ = new FileDescriptorTables();
internal::OnShutdown(&DeleteFileDescriptorTables);
}
inline void InitFileDescriptorTablesOnce() {
::google::protobuf::GoogleOnceInit(
&file_descriptor_tables_once_init_, &InitFileDescriptorTables);
}
} // anonymous namespace
inline const FileDescriptorTables& FileDescriptorTables::GetEmptyInstance() {
InitFileDescriptorTablesOnce();
return *file_descriptor_tables_;
}
void DescriptorPool::Tables::AddCheckpoint() {
checkpoints_.push_back(CheckPoint(this));
@ -3537,7 +3562,7 @@ FileDescriptor* DescriptorBuilder::NewPlaceholderFile(
placeholder->package_ = &internal::GetEmptyString();
placeholder->pool_ = pool_;
placeholder->options_ = &FileOptions::default_instance();
placeholder->tables_ = &FileDescriptorTables::kEmpty;
placeholder->tables_ = &FileDescriptorTables::GetEmptyInstance();
placeholder->source_code_info_ = &SourceCodeInfo::default_instance();
placeholder->is_placeholder_ = true;
placeholder->syntax_ = FileDescriptor::SYNTAX_PROTO2;

Loading…
Cancel
Save